Merge branch 'pm' into devel-stable
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 22 Sep 2011 21:39:23 +0000 (22:39 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 22 Sep 2011 21:39:23 +0000 (22:39 +0100)
1096 files changed:
Documentation/00-INDEX
Documentation/DocBook/media/v4l/controls.xml
Documentation/PCI/MSI-HOWTO.txt
Documentation/SubmittingDrivers
Documentation/SubmittingPatches
Documentation/block/cfq-iosched.txt
Documentation/email-clients.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/befs.txt
Documentation/hwmon/max16065
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-docs.txt
Documentation/kernel-parameters.txt
Documentation/networking/00-INDEX
Documentation/networking/ip-sysctl.txt
Documentation/networking/scaling.txt
Documentation/power/runtime_pm.txt
Documentation/ramoops.txt [new file with mode: 0644]
Documentation/virtual/00-INDEX
Documentation/virtual/lguest/lguest.c
Documentation/virtual/virtio-spec.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/alpha/include/asm/sysinfo.h
arch/alpha/include/asm/thread_info.h
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/systbls.S
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/boot/compressed/.gitignore
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/atags_to_fdt.c [new file with mode: 0644]
arch/arm/boot/compressed/head.S
arch/arm/boot/compressed/libfdt_env.h [new file with mode: 0644]
arch/arm/boot/compressed/misc.c
arch/arm/boot/compressed/mmcif-sh7372.c
arch/arm/boot/compressed/sdhi-sh7372.c
arch/arm/boot/compressed/string.c [new file with mode: 0644]
arch/arm/boot/compressed/vmlinux.lds.in
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/hardware/cache-l2x0.h
arch/arm/include/asm/hw_breakpoint.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/pmu.h
arch/arm/kernel/Makefile
arch/arm/kernel/calls.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/kprobes-arm.c
arch/arm/kernel/kprobes-test-arm.c [new file with mode: 0644]
arch/arm/kernel/kprobes-test-thumb.c [new file with mode: 0644]
arch/arm/kernel/kprobes-test.c [new file with mode: 0644]
arch/arm/kernel/kprobes-test.h [new file with mode: 0644]
arch/arm/kernel/kprobes-thumb.c
arch/arm/kernel/kprobes.h
arch/arm/kernel/perf_event.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/pmu.c
arch/arm/kernel/setup.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/include/mach/at91sam9g45.h
arch/arm/mach-bcmring/include/mach/memory.h
arch/arm/mach-bcmring/mm.c
arch/arm/mach-clps711x/autcpu12.c
arch/arm/mach-clps711x/cdb89712.c
arch/arm/mach-clps711x/ceiva.c
arch/arm/mach-clps711x/clep7312.c
arch/arm/mach-clps711x/edb7211-arch.c
arch/arm/mach-clps711x/fortunet.c
arch/arm/mach-clps711x/p720t.c
arch/arm/mach-cns3xxx/cns3420vb.c
arch/arm/mach-cns3xxx/include/mach/entry-macro.S
arch/arm/mach-cns3xxx/include/mach/system.h
arch/arm/mach-cns3xxx/include/mach/uncompress.h
arch/arm/mach-cns3xxx/pcie.c
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/common.c
arch/arm/mach-davinci/include/mach/memory.h
arch/arm/mach-davinci/include/mach/psc.h
arch/arm/mach-davinci/sleep.S
arch/arm/mach-dove/cm-a510.c
arch/arm/mach-dove/dove-db-setup.c
arch/arm/mach-ebsa110/core.c
arch/arm/mach-ep93xx/adssphere.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/gesbc9312.c
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-exynos4/clock.c
arch/arm/mach-exynos4/cpu.c
arch/arm/mach-exynos4/include/mach/irqs.h
arch/arm/mach-exynos4/include/mach/regs-pmu.h
arch/arm/mach-exynos4/irq-eint.c
arch/arm/mach-exynos4/mach-armlex4210.c
arch/arm/mach-exynos4/mach-nuri.c
arch/arm/mach-exynos4/mach-smdkc210.c
arch/arm/mach-exynos4/mach-smdkv310.c
arch/arm/mach-exynos4/mach-universal_c210.c
arch/arm/mach-exynos4/setup-usb-phy.c
arch/arm/mach-footbridge/cats-hw.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-footbridge/ebsa285.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/h7201-eval.c
arch/arm/mach-h720x/h7202-eval.c
arch/arm/mach-imx/mach-armadillo5x0.c
arch/arm/mach-imx/mach-cpuimx27.c
arch/arm/mach-imx/mach-cpuimx35.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-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-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-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-ixp2000/enp2611.c
arch/arm/mach-ixp2000/ixdp2400.c
arch/arm/mach-ixp2000/ixdp2800.c
arch/arm/mach-ixp2000/ixdp2x01.c
arch/arm/mach-ixp23xx/espresso.c
arch/arm/mach-ixp23xx/ixdp2351.c
arch/arm/mach-ixp23xx/roadrunner.c
arch/arm/mach-ixp4xx/avila-setup.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/ixdp425-setup.c
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-ixp4xx/vulcan-setup.c
arch/arm/mach-ixp4xx/wg302v2-setup.c
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-lpc32xx/phy3250.c
arch/arm/mach-msm/board-halibut.c
arch/arm/mach-msm/board-mahimahi.c
arch/arm/mach-msm/board-msm7x27.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-mv78xx0/buffalo-wxl-setup.c
arch/arm/mach-mv78xx0/db78x00-bp-setup.c
arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
arch/arm/mach-mx5/board-cpuimx51.c
arch/arm/mach-mx5/board-cpuimx51sd.c
arch/arm/mach-mx5/board-mx51_3ds.c
arch/arm/mach-mx5/board-mx51_babbage.c
arch/arm/mach-mx5/board-mx51_efikamx.c
arch/arm/mach-mx5/board-mx51_efikasb.c
arch/arm/mach-netx/nxdb500.c
arch/arm/mach-netx/nxdkn.c
arch/arm/mach-netx/nxeb500hmi.c
arch/arm/mach-nomadik/board-nhk8815.c
arch/arm/mach-nuc93x/mach-nuc932evb.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/io.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/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/powerdomain.c
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/edmini_v2-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/pci.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-pnx4008/core.c
arch/arm/mach-prima2/clock.c
arch/arm/mach-prima2/irq.c
arch/arm/mach-prima2/prima2.c
arch/arm/mach-prima2/rstc.c
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/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/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/littleton.c
arch/arm/mach-pxa/lpd270.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/raumfeld.c
arch/arm/mach-pxa/saar.c
arch/arm/mach-pxa/saarb.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-pxa/tavorevb.c
arch/arm/mach-pxa/tavorevb3.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/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-s3c2410/mach-amlm5900.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-n30.c
arch/arm/mach-s3c2410/mach-otom.c
arch/arm/mach-s3c2410/mach-qt2410.c
arch/arm/mach-s3c2410/mach-smdk2410.c
arch/arm/mach-s3c2410/mach-tct_hammer.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-s3c2412/mach-jive.c
arch/arm/mach-s3c2412/mach-smdk2413.c
arch/arm/mach-s3c2412/mach-vstms.c
arch/arm/mach-s3c2416/mach-smdk2416.c
arch/arm/mach-s3c2440/mach-anubis.c
arch/arm/mach-s3c2440/mach-at2440evb.c
arch/arm/mach-s3c2440/mach-gta02.c
arch/arm/mach-s3c2440/mach-mini2440.c
arch/arm/mach-s3c2440/mach-nexcoder.c
arch/arm/mach-s3c2440/mach-osiris.c
arch/arm/mach-s3c2440/mach-rx1950.c
arch/arm/mach-s3c2440/mach-rx3715.c
arch/arm/mach-s3c2440/mach-smdk2440.c
arch/arm/mach-s3c2443/mach-smdk2443.c
arch/arm/mach-s3c64xx/cpu.c
arch/arm/mach-s3c64xx/include/mach/memory.h
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-s3c64xx/pm.c
arch/arm/mach-s5p64x0/cpu.c
arch/arm/mach-s5p64x0/include/mach/memory.h
arch/arm/mach-s5p64x0/irq-eint.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/cpu.c
arch/arm/mach-s5pv210/include/mach/memory.h
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-s5pv210/pm.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/badge4.c
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/shannon.c
arch/arm/mach-sa1100/simpad.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-g3evm.c
arch/arm/mach-shmobile/board-g4evm.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-shmobile/include/mach/memory.h
arch/arm/mach-shmobile/include/mach/sh7372.h
arch/arm/mach-shmobile/intc-sh7372.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-spear3xx/spear300_evb.c
arch/arm/mach-spear3xx/spear310_evb.c
arch/arm/mach-spear3xx/spear320_evb.c
arch/arm/mach-spear6xx/spear600_evb.c
arch/arm/mach-tcc8k/board-tcc8000-sdk.c
arch/arm/mach-tegra/board-harmony.c
arch/arm/mach-tegra/board-paz00.c
arch/arm/mach-tegra/board-seaboard.c
arch/arm/mach-tegra/board-trimslice.c
arch/arm/mach-u300/core.c
arch/arm/mach-u300/include/mach/memory.h
arch/arm/mach-u300/u300.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-u5500.c
arch/arm/mach-versatile/versatile_ab.c
arch/arm/mach-versatile/versatile_pb.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-vt8500/bv07.c
arch/arm/mach-vt8500/wm8505_7in.c
arch/arm/mach-w90x900/mach-nuc910evb.c
arch/arm/mach-w90x900/mach-nuc950evb.c
arch/arm/mach-w90x900/mach-nuc960evb.c
arch/arm/mm/abort-macro.S
arch/arm/mm/cache-l2x0.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/plat-mxc/include/mach/memory.h
arch/arm/plat-omap/include/plat/io.h
arch/arm/plat-omap/include/plat/memory.h
arch/arm/plat-omap/io.c
arch/arm/plat-omap/omap_device.c
arch/arm/plat-s5p/clock.c
arch/arm/plat-s5p/irq-gpioint.c
arch/arm/plat-samsung/include/plat/backlight.h
arch/arm/plat-samsung/irq-vic-timer.c
arch/avr32/kernel/syscall_table.S
arch/blackfin/mach-common/entry.S
arch/cris/arch-v10/kernel/entry.S
arch/cris/arch-v32/kernel/entry.S
arch/cris/include/asm/serial.h [new file with mode: 0644]
arch/frv/kernel/entry.S
arch/h8300/kernel/syscalls.S
arch/ia64/Kconfig
arch/ia64/configs/generic_defconfig
arch/ia64/kernel/entry.S
arch/m32r/kernel/syscall_table.S
arch/m68k/include/asm/page_mm.h
arch/m68k/kernel/syscalltable.S
arch/microblaze/kernel/syscall_table.S
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mn10300/kernel/entry.S
arch/openrisc/include/asm/dma-mapping.h
arch/openrisc/include/asm/sigcontext.h
arch/openrisc/kernel/dma.c
arch/openrisc/kernel/signal.c
arch/parisc/kernel/syscall_table.S
arch/powerpc/boot/dts/p1023rds.dts
arch/powerpc/configs/85xx/p1023rds_defconfig
arch/powerpc/configs/corenet32_smp_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/include/asm/systbl.h
arch/powerpc/sysdev/fsl_rio.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/early.c
arch/s390/kernel/ipl.c
arch/s390/kernel/syscalls.S
arch/sh/include/asm/ptrace.h
arch/sh/kernel/cpu/sh4a/setup-sh7757.c
arch/sh/kernel/idle.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sh/kernel/traps_32.c
arch/sparc/Kconfig
arch/sparc/include/asm/sigcontext.h
arch/sparc/include/asm/spinlock_32.h
arch/sparc/include/asm/spinlock_64.h
arch/sparc/kernel/Makefile
arch/sparc/kernel/irq.h
arch/sparc/kernel/pcic.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sigutil.h [new file with mode: 0644]
arch/sparc/kernel/sigutil_32.c [new file with mode: 0644]
arch/sparc/kernel/sigutil_64.c [new file with mode: 0644]
arch/sparc/kernel/sys32.S
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/pvclock.h
arch/x86/include/asm/unistd_64.h
arch/x86/include/asm/xen/page.h
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/syscall_table_32.S
arch/x86/kvm/Kconfig
arch/x86/mm/fault.c
arch/x86/pci/acpi.c
arch/x86/platform/mrst/mrst.c
arch/x86/platform/olpc/olpc.c
arch/x86/vdso/vdso32/sysenter.S
arch/x86/xen/Makefile
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
arch/x86/xen/xen-asm_32.S
arch/xtensa/include/asm/unistd.h
block/Kconfig
block/Makefile
block/blk-core.c
block/blk-flush.c
block/blk-softirq.c
block/blk-throttle.c
block/blk.h
block/bsg-lib.c [new file with mode: 0644]
block/cfq-iosched.c
block/genhd.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/pata_imx.c [new file with mode: 0644]
drivers/ata/pata_via.c
drivers/ata/sata_dwc_460ex.c
drivers/ata/sata_sil.c
drivers/base/devres.c
drivers/base/devtmpfs.c
drivers/base/firmware_class.c
drivers/base/platform.c
drivers/base/power/clock_ops.c
drivers/base/power/domain.c
drivers/base/regmap/regmap-i2c.c
drivers/base/regmap/regmap-spi.c
drivers/base/regmap/regmap.c
drivers/bcma/main.c
drivers/block/Kconfig
drivers/block/drbd/drbd_nl.c
drivers/block/loop.c
drivers/block/swim3.c
drivers/block/xen-blkfront.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/cdrom/cdrom.c
drivers/char/msm_smd_pkt.c
drivers/clocksource/sh_cmt.c
drivers/dma/ste_dma40.c
drivers/edac/i7core_edac.c
drivers/firewire/core-cdev.c
drivers/firewire/core-device.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/firmware/google/gsmi.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/nouveau/nv04_crtc.c
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/radeon_clocks.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_test.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/hid/Kconfig
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-magicmouse.c
drivers/hid/hid-wacom.c
drivers/hid/hid-wiimote.c
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/i5k_amb.c
drivers/hwmon/ibmaem.c
drivers/hwmon/max16065.c
drivers/hwmon/ntc_thermistor.c
drivers/hwmon/pmbus/lm25066.c
drivers/hwmon/pmbus/pmbus.h
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/pmbus/ucd9000.c
drivers/hwmon/pmbus/ucd9200.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-pxa-pci.c
drivers/i2c/busses/i2c-tegra.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/input/joystick/analog.c
drivers/input/keyboard/ep93xx_keypad.c
drivers/input/keyboard/tegra-kbc.c
drivers/input/misc/ad714x-i2c.c
drivers/input/misc/ad714x-spi.c
drivers/input/misc/ad714x.c
drivers/input/misc/ad714x.h
drivers/input/misc/mma8450.c
drivers/input/misc/mpu3050.c
drivers/input/mouse/bcm5974.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/max11801_ts.c
drivers/input/touchscreen/tnetv107x-ts.c
drivers/iommu/amd_iommu.c
drivers/leds/leds-ams-delta.c
drivers/leds/leds-bd2802.c
drivers/leds/leds-hp6xx.c
drivers/md/linear.h
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/dvb/dvb-usb/vp7045.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/nuvoton-cir.h
drivers/media/video/gspca/ov519.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/via-camera.c
drivers/misc/Kconfig
drivers/misc/ab8500-pwm.c
drivers/misc/cb710/core.c
drivers/misc/fsa9480.c
drivers/misc/pti.c
drivers/misc/ti-st/st_core.c
drivers/misc/ti-st/st_kim.c
drivers/misc/ti-st/st_ll.c
drivers/mmc/card/mmc_test.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/host.h
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/sd.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mmc/host/tmio_mmc.c
drivers/mtd/ubi/debug.h
drivers/net/arm/am79c961a.c
drivers/net/bonding/bond_main.c
drivers/net/can/sja1000/plx_pci.c
drivers/net/can/ti_hecc.c
drivers/net/cassini.c
drivers/net/e1000e/e1000.h
drivers/net/e1000e/ich8lan.c
drivers/net/e1000e/netdev.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/gianfar_ethtool.c
drivers/net/ibmveth.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/phy/national.c
drivers/net/rionet.c
drivers/net/sh_eth.c
drivers/net/usb/cdc_ncm.c
drivers/net/via-velocity.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/iwlwifi/iwl-pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/testmode.c
drivers/pci/hotplug/pcihp_slot.c
drivers/pci/of.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/power/max8997_charger.c
drivers/power/max8998_charger.c
drivers/power/s3c_adc_battery.c
drivers/rapidio/rio-scan.c
drivers/rtc/interface.c
drivers/rtc/rtc-ep93xx.c
drivers/rtc/rtc-lib.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-twl.c
drivers/s390/block/dasd_ioctl.c
drivers/s390/char/sclp_cmd.c
drivers/scsi/qla4xxx/Kconfig
drivers/sh/intc/chip.c
drivers/staging/brcm80211/brcmsmac/otp.c
drivers/staging/brcm80211/brcmsmac/types.h
drivers/staging/gma500/mdfld_dsi_dbi.c
drivers/staging/gma500/mdfld_dsi_dbi.h
drivers/staging/gma500/mdfld_dsi_dpi.c
drivers/staging/gma500/mdfld_dsi_output.c
drivers/staging/gma500/medfield.h
drivers/staging/gma500/psb_drv.h
drivers/staging/octeon/ethernet-rgmii.c
drivers/staging/octeon/ethernet-spi.c
drivers/staging/tidspbridge/core/dsp-clock.c
drivers/staging/zcache/tmem.c
drivers/staging/zcache/zcache-main.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/target_core_cdb.c
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_pr.c
drivers/target/target_core_rd.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_conf.c
drivers/tty/pty.c
drivers/tty/serial/8250.c
drivers/tty/serial/8250_pci.c
drivers/tty/serial/8250_pnp.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/max3107-aava.c
drivers/tty/serial/max3107.c
drivers/tty/serial/mrst_max3110.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/samsung.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/ucc_uart.c
drivers/tty/tty_io.c
drivers/usb/core/hcd.c
drivers/usb/gadget/f_phonet.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-s5p.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/musb/blackfin.c
drivers/usb/musb/cppi_dma.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_regs.h
drivers/usb/musb/tusb6010.c
drivers/usb/musb/tusb6010_omap.c
drivers/usb/musb/ux500_dma.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/option.c
drivers/video/backlight/adp8870_bl.c
drivers/video/backlight/backlight.c
drivers/video/backlight/ep93xx_bl.c
drivers/video/backlight/pwm_bl.c
drivers/w1/masters/ds2490.c
drivers/w1/masters/matrox_w1.c
drivers/w1/slaves/w1_ds2408.c
drivers/w1/slaves/w1_smem.c
drivers/w1/slaves/w1_therm.c
drivers/w1/w1.c
drivers/w1/w1.h
drivers/w1/w1_family.c
drivers/w1/w1_family.h
drivers/w1/w1_int.c
drivers/w1/w1_int.h
drivers/w1/w1_io.c
drivers/w1/w1_log.h
drivers/w1/w1_netlink.c
drivers/w1/w1_netlink.h
drivers/xen/xen-selfballoon.c
fs/9p/v9fs_vfs.h
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/9p/vfs_super.c
fs/befs/linuxvfs.c
fs/block_dev.c
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/btrfs/xattr.c
fs/ceph/mds_client.c
fs/ceph/super.c
fs/cifs/cifs_debug.c
fs/cifs/cifsacl.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/transport.c
fs/compat.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.h
fs/ext4/indirect.c
fs/ext4/inode.c
fs/ext4/page-io.c
fs/ext4/super.c
fs/fat/dir.c
fs/fat/inode.c
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/jfs/jfs_umount.c
fs/namei.c
fs/nfs/blocklayout/blocklayout.c
fs/nfs/callback.h
fs/nfs/callback_proc.c
fs/nfs/callback_xdr.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/objlayout/pnfs_osd_xdr_cli.c
fs/ubifs/debug.h
fs/xfs/Makefile
fs/xfs/kmem.c [moved from fs/xfs/linux-2.6/kmem.c with 100% similarity]
fs/xfs/kmem.h [moved from fs/xfs/linux-2.6/kmem.h with 100% similarity]
fs/xfs/mrlock.h [moved from fs/xfs/linux-2.6/mrlock.h with 100% similarity]
fs/xfs/time.h [moved from fs/xfs/linux-2.6/time.h with 100% similarity]
fs/xfs/uuid.c [moved from fs/xfs/support/uuid.c with 100% similarity]
fs/xfs/uuid.h [moved from fs/xfs/support/uuid.h with 100% similarity]
fs/xfs/xfs.h
fs/xfs/xfs_acl.c [moved from fs/xfs/linux-2.6/xfs_acl.c with 100% similarity]
fs/xfs/xfs_aops.c [moved from fs/xfs/linux-2.6/xfs_aops.c with 100% similarity]
fs/xfs/xfs_aops.h [moved from fs/xfs/linux-2.6/xfs_aops.h with 100% similarity]
fs/xfs/xfs_buf.c [moved from fs/xfs/linux-2.6/xfs_buf.c with 100% similarity]
fs/xfs/xfs_buf.h [moved from fs/xfs/linux-2.6/xfs_buf.h with 100% similarity]
fs/xfs/xfs_discard.c [moved from fs/xfs/linux-2.6/xfs_discard.c with 100% similarity]
fs/xfs/xfs_discard.h [moved from fs/xfs/linux-2.6/xfs_discard.h with 100% similarity]
fs/xfs/xfs_dquot.c [moved from fs/xfs/quota/xfs_dquot.c with 100% similarity]
fs/xfs/xfs_dquot.h [moved from fs/xfs/quota/xfs_dquot.h with 100% similarity]
fs/xfs/xfs_dquot_item.c [moved from fs/xfs/quota/xfs_dquot_item.c with 100% similarity]
fs/xfs/xfs_dquot_item.h [moved from fs/xfs/quota/xfs_dquot_item.h with 100% similarity]
fs/xfs/xfs_export.c [moved from fs/xfs/linux-2.6/xfs_export.c with 100% similarity]
fs/xfs/xfs_export.h [moved from fs/xfs/linux-2.6/xfs_export.h with 100% similarity]
fs/xfs/xfs_file.c [moved from fs/xfs/linux-2.6/xfs_file.c with 100% similarity]
fs/xfs/xfs_fs_subr.c [moved from fs/xfs/linux-2.6/xfs_fs_subr.c with 100% similarity]
fs/xfs/xfs_globals.c [moved from fs/xfs/linux-2.6/xfs_globals.c with 100% similarity]
fs/xfs/xfs_ioctl.c [moved from fs/xfs/linux-2.6/xfs_ioctl.c with 100% similarity]
fs/xfs/xfs_ioctl.h [moved from fs/xfs/linux-2.6/xfs_ioctl.h with 100% similarity]
fs/xfs/xfs_ioctl32.c [moved from fs/xfs/linux-2.6/xfs_ioctl32.c with 100% similarity]
fs/xfs/xfs_ioctl32.h [moved from fs/xfs/linux-2.6/xfs_ioctl32.h with 100% similarity]
fs/xfs/xfs_iops.c [moved from fs/xfs/linux-2.6/xfs_iops.c with 99% similarity]
fs/xfs/xfs_iops.h [moved from fs/xfs/linux-2.6/xfs_iops.h with 100% similarity]
fs/xfs/xfs_linux.h [moved from fs/xfs/linux-2.6/xfs_linux.h with 96% similarity]
fs/xfs/xfs_message.c [moved from fs/xfs/linux-2.6/xfs_message.c with 100% similarity]
fs/xfs/xfs_message.h [moved from fs/xfs/linux-2.6/xfs_message.h with 100% similarity]
fs/xfs/xfs_qm.c [moved from fs/xfs/quota/xfs_qm.c with 100% similarity]
fs/xfs/xfs_qm.h [moved from fs/xfs/quota/xfs_qm.h with 100% similarity]
fs/xfs/xfs_qm_bhv.c [moved from fs/xfs/quota/xfs_qm_bhv.c with 100% similarity]
fs/xfs/xfs_qm_stats.c [moved from fs/xfs/quota/xfs_qm_stats.c with 100% similarity]
fs/xfs/xfs_qm_stats.h [moved from fs/xfs/quota/xfs_qm_stats.h with 100% similarity]
fs/xfs/xfs_qm_syscalls.c [moved from fs/xfs/quota/xfs_qm_syscalls.c with 100% similarity]
fs/xfs/xfs_quota_priv.h [moved from fs/xfs/quota/xfs_quota_priv.h with 100% similarity]
fs/xfs/xfs_quotaops.c [moved from fs/xfs/linux-2.6/xfs_quotaops.c with 99% similarity]
fs/xfs/xfs_stats.c [moved from fs/xfs/linux-2.6/xfs_stats.c with 100% similarity]
fs/xfs/xfs_stats.h [moved from fs/xfs/linux-2.6/xfs_stats.h with 100% similarity]
fs/xfs/xfs_super.c [moved from fs/xfs/linux-2.6/xfs_super.c with 98% similarity]
fs/xfs/xfs_super.h [moved from fs/xfs/linux-2.6/xfs_super.h with 100% similarity]
fs/xfs/xfs_sync.c [moved from fs/xfs/linux-2.6/xfs_sync.c with 100% similarity]
fs/xfs/xfs_sync.h [moved from fs/xfs/linux-2.6/xfs_sync.h with 100% similarity]
fs/xfs/xfs_sysctl.c [moved from fs/xfs/linux-2.6/xfs_sysctl.c with 100% similarity]
fs/xfs/xfs_sysctl.h [moved from fs/xfs/linux-2.6/xfs_sysctl.h with 100% similarity]
fs/xfs/xfs_trace.c [moved from fs/xfs/linux-2.6/xfs_trace.c with 96% similarity]
fs/xfs/xfs_trace.h [moved from fs/xfs/linux-2.6/xfs_trace.h with 100% similarity]
fs/xfs/xfs_trans_dquot.c [moved from fs/xfs/quota/xfs_trans_dquot.c with 100% similarity]
fs/xfs/xfs_vnode.h [moved from fs/xfs/linux-2.6/xfs_vnode.h with 100% similarity]
fs/xfs/xfs_xattr.c [moved from fs/xfs/linux-2.6/xfs_xattr.c with 100% similarity]
include/asm-generic/memory_model.h
include/asm-generic/unistd.h
include/linux/blk_types.h
include/linux/blkdev.h
include/linux/blktrace_api.h
include/linux/bsg-lib.h [new file with mode: 0644]
include/linux/compat.h
include/linux/connector.h
include/linux/fs.h
include/linux/fuse.h
include/linux/hash.h
include/linux/irq.h
include/linux/irqdesc.h
include/linux/loop.h
include/linux/miscdevice.h
include/linux/mm.h
include/linux/mmc/host.h
include/linux/pci.h
include/linux/perf_event.h
include/linux/personality.h
include/linux/pm_domain.h
include/linux/pwm_backlight.h
include/linux/regulator/consumer.h
include/linux/rio_regs.h
include/linux/rtc.h
include/linux/syscalls.h
include/linux/ti_wilink_st.h
include/linux/tty.h
include/linux/tty_driver.h
include/linux/writeback.h
include/net/9p/9p.h
include/net/cfg80211.h
include/sound/tlv320aic3x.h
include/target/target_core_fabric_ops.h
include/trace/events/block.h
kernel/events/core.c
kernel/irq/generic-chip.c
kernel/irq/irqdesc.c
kernel/irq/manage.c
kernel/lockdep.c
kernel/power/Kconfig
kernel/printk.c
kernel/sched.c
kernel/sys.c
kernel/sys_ni.c
kernel/sysctl_binary.c
kernel/sysctl_check.c
kernel/time/alarmtimer.c
kernel/trace/blktrace.c
lib/Makefile
mm/highmem.c
mm/memcontrol.c
mm/page-writeback.c
mm/vmalloc.c
mm/vmscan.c
net/8021q/vlan_core.c
net/9p/trans_virtio.c
net/atm/br2684.c
net/bluetooth/af_bluetooth.c
net/bluetooth/bnep/bnep.h
net/bluetooth/bnep/core.c
net/bluetooth/cmtp/capi.c
net/bluetooth/cmtp/cmtp.h
net/bluetooth/cmtp/core.c
net/bluetooth/hci_core.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/bridge/br_if.c
net/bridge/br_multicast.c
net/ceph/msgpool.c
net/ceph/osd_client.c
net/core/neighbour.c
net/core/netpoll.c
net/ipv4/igmp.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mcast.c
net/ipv6/sit.c
net/mac80211/main.c
net/sched/act_mirred.c
net/socket.c
net/wireless/core.c
net/wireless/sysfs.c
scripts/checkpatch.pl
scripts/get_maintainer.pl
sound/aoa/fabrics/layout.c
sound/pci/ac97/ac97_patch.c
sound/pci/azt3328.c
sound/pci/hda/alc268_quirks.c
sound/pci/hda/hda_eld.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/blackfin/bf5xx-ad193x.c
sound/soc/codecs/ad193x.c
sound/soc/codecs/ad193x.h
sound/soc/codecs/sta32x.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8996.c
sound/soc/ep93xx/ep93xx-i2s.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/fsl/p1022_ds.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/omap/ams-delta.c
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.h
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap-pcm.h
sound/soc/omap/rx51.c
sound/soc/samsung/Kconfig
sound/soc/samsung/Makefile
sound/soc/samsung/h1940_uda1380.c
sound/soc/samsung/idma.c [new file with mode: 0644]
sound/soc/samsung/idma.h [new file with mode: 0644]
sound/soc/samsung/jive_wm8750.c
sound/soc/samsung/rx1950_uda1380.c
sound/soc/samsung/speyside_wm8962.c
sound/soc/soc-core.c
sound/soc/soc-io.c
sound/soc/soc-jack.c
sound/soc/soc-pcm.c
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_wm8903.c
sound/usb/caiaq/audio.c
sound/usb/caiaq/device.h
sound/usb/mixer.c
sound/usb/quirks-table.h
tools/perf/builtin-probe.c
tools/perf/builtin-record.c
tools/perf/builtin-stat.c
tools/perf/util/dwarf-aux.c
tools/perf/util/dwarf-aux.h
tools/perf/util/evlist.c
tools/perf/util/header.c
tools/perf/util/include/linux/compiler.h
tools/perf/util/parse-events.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/ui/browsers/top.c
tools/power/cpupower/Makefile
tools/power/cpupower/debug/x86_64/Makefile
tools/power/cpupower/debug/x86_64/centrino-decode.c [deleted symlink]
tools/power/cpupower/debug/x86_64/powernow-k8-decode.c [deleted symlink]
tools/power/cpupower/man/cpupower-frequency-info.1
tools/power/cpupower/man/cpupower-frequency-set.1
tools/power/cpupower/man/cpupower.1
tools/power/cpupower/utils/builtin.h
tools/power/cpupower/utils/cpufreq-info.c
tools/power/cpupower/utils/cpufreq-set.c
tools/power/cpupower/utils/cpuidle-info.c
tools/power/cpupower/utils/cpupower-info.c
tools/power/cpupower/utils/cpupower-set.c
tools/power/cpupower/utils/cpupower.c
tools/power/cpupower/utils/helpers/helpers.h
tools/power/cpupower/utils/helpers/sysfs.c
tools/power/cpupower/utils/helpers/sysfs.h
tools/power/cpupower/utils/helpers/topology.c
tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c

index 1f89424..65bbd26 100644 (file)
@@ -272,6 +272,8 @@ printk-formats.txt
        - how to get printk format specifiers right
 prio_tree.txt
        - info on radix-priority-search-tree use for indexing vmas.
+ramoops.txt
+       - documentation of the ramoops oops/panic logging module.
 rbtree.txt
        - info on what red-black trees are and what they are for.
 robust-futex-ABI.txt
index 8516401..23fdf79 100644 (file)
@@ -1455,7 +1455,7 @@ Applicable to the H264 encoder.</entry>
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-h264-vui-sar-idc">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC</constant>&nbsp;</entry>
                <entry>enum&nbsp;v4l2_mpeg_video_h264_vui_sar_idc</entry>
              </row>
@@ -1561,7 +1561,7 @@ Applicable to the H264 encoder.</entry>
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-h264-level">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_LEVEL</constant>&nbsp;</entry>
                <entry>enum&nbsp;v4l2_mpeg_video_h264_level</entry>
              </row>
@@ -1641,7 +1641,7 @@ Possible values are:</entry>
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-mpeg4-level">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL</constant>&nbsp;</entry>
                <entry>enum&nbsp;v4l2_mpeg_video_mpeg4_level</entry>
              </row>
@@ -1689,9 +1689,9 @@ Possible values are:</entry>
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-h264-profile">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_PROFILE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_h264_profile</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_profile</entry>
              </row>
              <row><entry spanname="descr">The profile information for H264.
 Applicable to the H264 encoder.
@@ -1774,9 +1774,9 @@ Possible values are:</entry>
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-mpeg4-profile">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_mpeg4_profile</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_mpeg4_profile</entry>
              </row>
              <row><entry spanname="descr">The profile information for MPEG4.
 Applicable to the MPEG4 encoder.
@@ -1820,9 +1820,9 @@ Applicable to the encoder.
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-multi-slice-mode">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_multi_slice_mode</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_multi_slice_mode</entry>
              </row>
              <row><entry spanname="descr">Determines how the encoder should handle division of frame into slices.
 Applicable to the encoder.
@@ -1868,9 +1868,9 @@ Applicable to the encoder.</entry>
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-h264-loop-filter-mode">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_h264_loop_filter_mode</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_loop_filter_mode</entry>
              </row>
              <row><entry spanname="descr">Loop filter mode for H264 encoder.
 Possible values are:</entry>
@@ -1913,9 +1913,9 @@ Applicable to the H264 encoder.</entry>
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-h264-entropy-mode">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_h264_symbol_mode</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_h264_entropy_mode</entry>
              </row>
              <row><entry spanname="descr">Entropy coding mode for H264 - CABAC/CAVALC.
 Applicable to the H264 encoder.
@@ -2140,9 +2140,9 @@ previous frames. Applicable to the H264 encoder.</entry>
              </row>
 
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-video-header-mode">
                <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_HEADER_MODE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_header_mode</entry>
+               <entry>enum&nbsp;v4l2_mpeg_video_header_mode</entry>
              </row>
              <row><entry spanname="descr">Determines whether the header is returned as the first buffer or is
 it returned together with the first frame. Applicable to encoders.
@@ -2320,9 +2320,9 @@ Valid only when H.264 and macroblock level RC is enabled (<constant>V4L2_CID_MPE
 Applicable to the H264 encoder.</entry>
              </row>
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-mfc51-video-frame-skip-mode">
                <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_mfc51_frame_skip_mode</entry>
+               <entry>enum&nbsp;v4l2_mpeg_mfc51_video_frame_skip_mode</entry>
              </row>
              <row><entry spanname="descr">
 Indicates in what conditions the encoder should skip frames. If encoding a frame would cause the encoded stream to be larger then
@@ -2361,9 +2361,9 @@ the stream will meet tight bandwidth contraints. Applicable to encoders.
 </entry>
              </row>
              <row><entry></entry></row>
-             <row>
+             <row id="v4l2-mpeg-mfc51-video-force-frame-type">
                <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE</constant>&nbsp;</entry>
-               <entry>enum&nbsp;v4l2_mpeg_mfc51_force_frame_type</entry>
+               <entry>enum&nbsp;v4l2_mpeg_mfc51_video_force_frame_type</entry>
              </row>
              <row><entry spanname="descr">Force a frame type for the next queued buffer. Applicable to encoders.
 Possible values are:</entry>
index 3f5e0b0..53e6fca 100644 (file)
@@ -45,7 +45,7 @@ arrived in memory (this becomes more likely with devices behind PCI-PCI
 bridges).  In order to ensure that all the data has arrived in memory,
 the interrupt handler must read a register on the device which raised
 the interrupt.  PCI transaction ordering rules require that all the data
-arrives in memory before the value can be returned from the register.
+arrive in memory before the value may be returned from the register.
 Using MSIs avoids this problem as the interrupt-generating write cannot
 pass the data writes, so by the time the interrupt is raised, the driver
 knows that all the data has arrived in memory.
@@ -86,13 +86,13 @@ device.
 
 int pci_enable_msi(struct pci_dev *dev)
 
-A successful call will allocate ONE interrupt to the device, regardless
-of how many MSIs the device supports.  The device will be switched from
+A successful call allocates ONE interrupt to the device, regardless
+of how many MSIs the device supports.  The device is switched from
 pin-based interrupt mode to MSI mode.  The dev->irq number is changed
-to a new number which represents the message signaled interrupt.
-This function should be called before the driver calls request_irq()
-since enabling MSIs disables the pin-based IRQ and the driver will not
-receive interrupts on the old interrupt.
+to a new number which represents the message signaled interrupt;
+consequently, this function should be called before the driver calls
+request_irq(), because an MSI is delivered via a vector that is
+different from the vector of a pin-based interrupt.
 
 4.2.2 pci_enable_msi_block
 
@@ -111,20 +111,20 @@ the device are in the range dev->irq to dev->irq + count - 1.
 
 If this function returns a negative number, it indicates an error and
 the driver should not attempt to request any more MSI interrupts for
-this device.  If this function returns a positive number, it will be
-less than 'count' and indicate the number of interrupts that could have
-been allocated.  In neither case will the irq value have been
-updated, nor will the device have been switched into MSI mode.
+this device.  If this function returns a positive number, it is
+less than 'count' and indicates the number of interrupts that could have
+been allocated.  In neither case is the irq value updated or the device
+switched into MSI mode.
 
 The device driver must decide what action to take if
-pci_enable_msi_block() returns a value less than the number asked for.
-Some devices can make use of fewer interrupts than the maximum they
-request; in this case the driver should call pci_enable_msi_block()
+pci_enable_msi_block() returns a value less than the number requested.
+For instance, the driver could still make use of fewer interrupts;
+in this case the driver should call pci_enable_msi_block()
 again.  Note that it is not guaranteed to succeed, even when the
 'count' has been reduced to the value returned from a previous call to
 pci_enable_msi_block().  This is because there are multiple constraints
 on the number of vectors that can be allocated; pci_enable_msi_block()
-will return as soon as it finds any constraint that doesn't allow the
+returns as soon as it finds any constraint that doesn't allow the
 call to succeed.
 
 4.2.3 pci_disable_msi
@@ -137,10 +137,10 @@ interrupt number and frees the previously allocated message signaled
 interrupt(s).  The interrupt may subsequently be assigned to another
 device, so drivers should not cache the value of dev->irq.
 
-A device driver must always call free_irq() on the interrupt(s)
-for which it has called request_irq() before calling this function.
-Failure to do so will result in a BUG_ON(), the device will be left with
-MSI enabled and will leak its vector.
+Before calling this function, a device driver must always call free_irq()
+on any interrupt for which it previously called request_irq().
+Failure to do so results in a BUG_ON(), leaving the device with
+MSI enabled and thus leaking its vector.
 
 4.3 Using MSI-X
 
@@ -155,10 +155,10 @@ struct msix_entry {
 };
 
 This allows for the device to use these interrupts in a sparse fashion;
-for example it could use interrupts 3 and 1027 and allocate only a
+for example, it could use interrupts 3 and 1027 and yet allocate only a
 two-element array.  The driver is expected to fill in the 'entry' value
-in each element of the array to indicate which entries it wants the kernel
-to assign interrupts for.  It is invalid to fill in two entries with the
+in each element of the array to indicate for which entries the kernel
+should assign interrupts; it is invalid to fill in two entries with the
 same number.
 
 4.3.1 pci_enable_msix
@@ -168,10 +168,11 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
 Calling this function asks the PCI subsystem to allocate 'nvec' MSIs.
 The 'entries' argument is a pointer to an array of msix_entry structs
 which should be at least 'nvec' entries in size.  On success, the
-function will return 0 and the device will have been switched into
-MSI-X interrupt mode.  The 'vector' elements in each entry will have
-been filled in with the interrupt number.  The driver should then call
-request_irq() for each 'vector' that it decides to use.
+device is switched into MSI-X mode and the function returns 0.
+The 'vector' member in each entry is populated with the interrupt number;
+the driver should then call request_irq() for each 'vector' that it
+decides to use.  The device driver is responsible for keeping track of the
+interrupts assigned to the MSI-X vectors so it can free them again later.
 
 If this function returns a negative number, it indicates an error and
 the driver should not attempt to allocate any more MSI-X interrupts for
@@ -181,16 +182,14 @@ below.
 
 This function, in contrast with pci_enable_msi(), does not adjust
 dev->irq.  The device will not generate interrupts for this interrupt
-number once MSI-X is enabled.  The device driver is responsible for
-keeping track of the interrupts assigned to the MSI-X vectors so it can
-free them again later.
+number once MSI-X is enabled.
 
 Device drivers should normally call this function once per device
 during the initialization phase.
 
-It is ideal if drivers can cope with a variable number of MSI-X interrupts,
+It is ideal if drivers can cope with a variable number of MSI-X interrupts;
 there are many reasons why the platform may not be able to provide the
-exact number a driver asks for.
+exact number that a driver asks for.
 
 A request loop to achieve that might look like:
 
@@ -212,15 +211,15 @@ static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 
 void pci_disable_msix(struct pci_dev *dev)
 
-This API should be used to undo the effect of pci_enable_msix().  It frees
+This function should be used to undo the effect of pci_enable_msix().  It frees
 the previously allocated message signaled interrupts.  The interrupts may
 subsequently be assigned to another device, so drivers should not cache
 the value of the 'vector' elements over a call to pci_disable_msix().
 
-A device driver must always call free_irq() on the interrupt(s)
-for which it has called request_irq() before calling this function.
-Failure to do so will result in a BUG_ON(), the device will be left with
-MSI enabled and will leak its vector.
+Before calling this function, a device driver must always call free_irq()
+on any interrupt for which it previously called request_irq().
+Failure to do so results in a BUG_ON(), leaving the device with
+MSI-X enabled and thus leaking its vector.
 
 4.3.3 The MSI-X Table
 
@@ -232,10 +231,10 @@ mask or unmask an interrupt, it should call disable_irq() / enable_irq().
 4.4 Handling devices implementing both MSI and MSI-X capabilities
 
 If a device implements both MSI and MSI-X capabilities, it can
-run in either MSI mode or MSI-X mode but not both simultaneously.
+run in either MSI mode or MSI-X mode, but not both simultaneously.
 This is a requirement of the PCI spec, and it is enforced by the
 PCI layer.  Calling pci_enable_msi() when MSI-X is already enabled or
-pci_enable_msix() when MSI is already enabled will result in an error.
+pci_enable_msix() when MSI is already enabled results in an error.
 If a device driver wishes to switch between MSI and MSI-X at runtime,
 it must first quiesce the device, then switch it back to pin-interrupt
 mode, before calling pci_enable_msi() or pci_enable_msix() and resuming
@@ -251,7 +250,7 @@ the MSI-X facilities in preference to the MSI facilities.  As mentioned
 above, MSI-X supports any number of interrupts between 1 and 2048.
 In constrast, MSI is restricted to a maximum of 32 interrupts (and
 must be a power of two).  In addition, the MSI interrupt vectors must
-be allocated consecutively, so the system may not be able to allocate
+be allocated consecutively, so the system might not be able to allocate
 as many vectors for MSI as it could for MSI-X.  On some platforms, MSI
 interrupts must all be targeted at the same set of CPUs whereas MSI-X
 interrupts can all be targeted at different CPUs.
@@ -281,7 +280,7 @@ disabled to enabled and back again.
 
 Using 'lspci -v' (as root) may show some devices with "MSI", "Message
 Signalled Interrupts" or "MSI-X" capabilities.  Each of these capabilities
-has an 'Enable' flag which will be followed with either "+" (enabled)
+has an 'Enable' flag which is followed with either "+" (enabled)
 or "-" (disabled).
 
 
@@ -298,7 +297,7 @@ The PCI stack provides three ways to disable MSIs:
 
 Some host chipsets simply don't support MSIs properly.  If we're
 lucky, the manufacturer knows this and has indicated it in the ACPI
-FADT table.  In this case, Linux will automatically disable MSIs.
+FADT table.  In this case, Linux automatically disables MSIs.
 Some boards don't include this information in the table and so we have
 to detect them ourselves.  The complete list of these is found near the
 quirk_disable_all_msi() function in drivers/pci/quirks.c.
@@ -317,7 +316,7 @@ Some bridges allow you to enable MSIs by changing some bits in their
 PCI configuration space (especially the Hypertransport chipsets such
 as the nVidia nForce and Serverworks HT2000).  As with host chipsets,
 Linux mostly knows about them and automatically enables MSIs if it can.
-If you have a bridge which Linux doesn't yet know about, you can enable
+If you have a bridge unknown to Linux, you can enable
 MSIs in configuration space using whatever method you know works, then
 enable MSIs on that bridge by doing:
 
@@ -327,7 +326,7 @@ where $bridge is the PCI address of the bridge you've enabled (eg
 0000:00:0e.0).
 
 To disable MSIs, echo 0 instead of 1.  Changing this value should be
-done with caution as it can break interrupt handling for all devices
+done with caution as it could break interrupt handling for all devices
 below this bridge.
 
 Again, please notify linux-pci@vger.kernel.org of any bridges that need
@@ -336,7 +335,7 @@ special handling.
 5.3. Disabling MSIs on a single device
 
 Some devices are known to have faulty MSI implementations.  Usually this
-is handled in the individual device driver but occasionally it's necessary
+is handled in the individual device driver, but occasionally it's necessary
 to handle this with a quirk.  Some drivers have an option to disable use
 of MSI.  While this is a convenient workaround for the driver author,
 it is not good practise, and should not be emulated.
@@ -350,7 +349,7 @@ for your machine.  You should also check your .config to be sure you
 have enabled CONFIG_PCI_MSI.
 
 Then, 'lspci -t' gives the list of bridges above a device.  Reading
-/sys/bus/pci/devices/*/msi_bus will tell you whether MSI are enabled (1)
+/sys/bus/pci/devices/*/msi_bus will tell you whether MSIs are enabled (1)
 or disabled (0).  If 0 is found in any of the msi_bus files belonging
 to bridges between the PCI root and the device, MSIs are disabled.
 
index 319baa8..36d16bb 100644 (file)
@@ -130,7 +130,7 @@ Linux kernel master tree:
        ftp.??.kernel.org:/pub/linux/kernel/...
        ?? == your country code, such as "us", "uk", "fr", etc.
 
-       http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git
+       http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git
 
 Linux kernel mailing list:
        linux-kernel@vger.kernel.org
index 569f353..4468ce2 100644 (file)
@@ -303,7 +303,7 @@ patches that are being emailed around.
 
 The sign-off is a simple line at the end of the explanation for the
 patch, which certifies that you wrote it or otherwise have the right to
-pass it on as a open-source patch.  The rules are pretty simple: if you
+pass it on as an open-source patch.  The rules are pretty simple: if you
 can certify the below:
 
         Developer's Certificate of Origin 1.1
index e578fee..6d670f5 100644 (file)
@@ -43,3 +43,74 @@ If one sets slice_idle=0 and if storage supports NCQ, CFQ internally switches
 to IOPS mode and starts providing fairness in terms of number of requests
 dispatched. Note that this mode switching takes effect only for group
 scheduling. For non-cgroup users nothing should change.
+
+CFQ IO scheduler Idling Theory
+===============================
+Idling on a queue is primarily about waiting for the next request to come
+on same queue after completion of a request. In this process CFQ will not
+dispatch requests from other cfq queues even if requests are pending there.
+
+The rationale behind idling is that it can cut down on number of seeks
+on rotational media. For example, if a process is doing dependent
+sequential reads (next read will come on only after completion of previous
+one), then not dispatching request from other queue should help as we
+did not move the disk head and kept on dispatching sequential IO from
+one queue.
+
+CFQ has following service trees and various queues are put on these trees.
+
+       sync-idle       sync-noidle     async
+
+All cfq queues doing synchronous sequential IO go on to sync-idle tree.
+On this tree we idle on each queue individually.
+
+All synchronous non-sequential queues go on sync-noidle tree. Also any
+request which are marked with REQ_NOIDLE go on this service tree. On this
+tree we do not idle on individual queues instead idle on the whole group
+of queues or the tree. So if there are 4 queues waiting for IO to dispatch
+we will idle only once last queue has dispatched the IO and there is
+no more IO on this service tree.
+
+All async writes go on async service tree. There is no idling on async
+queues.
+
+CFQ has some optimizations for SSDs and if it detects a non-rotational
+media which can support higher queue depth (multiple requests at in
+flight at a time), then it cuts down on idling of individual queues and
+all the queues move to sync-noidle tree and only tree idle remains. This
+tree idling provides isolation with buffered write queues on async tree.
+
+FAQ
+===
+Q1. Why to idle at all on queues marked with REQ_NOIDLE.
+
+A1. We only do tree idle (all queues on sync-noidle tree) on queues marked
+    with REQ_NOIDLE. This helps in providing isolation with all the sync-idle
+    queues. Otherwise in presence of many sequential readers, other
+    synchronous IO might not get fair share of disk.
+
+    For example, if there are 10 sequential readers doing IO and they get
+    100ms each. If a REQ_NOIDLE request comes in, it will be scheduled
+    roughly after 1 second. If after completion of REQ_NOIDLE request we
+    do not idle, and after a couple of milli seconds a another REQ_NOIDLE
+    request comes in, again it will be scheduled after 1second. Repeat it
+    and notice how a workload can lose its disk share and suffer due to
+    multiple sequential readers.
+
+    fsync can generate dependent IO where bunch of data is written in the
+    context of fsync, and later some journaling data is written. Journaling
+    data comes in only after fsync has finished its IO (atleast for ext4
+    that seemed to be the case). Now if one decides not to idle on fsync
+    thread due to REQ_NOIDLE, then next journaling write will not get
+    scheduled for another second. A process doing small fsync, will suffer
+    badly in presence of multiple sequential readers.
+
+    Hence doing tree idling on threads using REQ_NOIDLE flag on requests
+    provides isolation from multiple sequential readers and at the same
+    time we do not idle on individual threads.
+
+Q2. When to specify REQ_NOIDLE
+A2. I would think whenever one is doing synchronous write and not expecting
+    more writes to be dispatched from same context soon, should be able
+    to specify REQ_NOIDLE on writes and that probably should work well for
+    most of the cases.
index a0b58e2..860c29a 100644 (file)
@@ -199,18 +199,16 @@ to coerce it into behaving.
 
 To beat some sense out of the internal editor, do this:
 
-- Under account settings, composition and addressing, uncheck "Compose
-  messages in HTML format".
-
 - Edit your Thunderbird config settings so that it won't use format=flowed.
   Go to "edit->preferences->advanced->config editor" to bring up the
   thunderbird's registry editor, and set "mailnews.send_plaintext_flowed" to
   "false".
 
-- Enable "preformat" mode: Shft-click on the Write icon to bring up the HTML
-  composer, select "Preformat" from the drop-down box just under the subject
-  line, then close the message without saving.  (This setting also applies to
-  the text composer, but the only control for it is in the HTML composer.)
+- Disable HTML Format: Set "mail.identity.id1.compose_html" to "false".
+
+- Enable "preformat" mode: Set "editor.quotesPreformatted" to "true".
+
+- Enable UTF8: Set "prefs.converted-to-utf8" to "true".
 
 - Install the "toggle wordwrap" extension.  Download the file from:
     https://addons.mozilla.org/thunderbird/addon/2351/
index c4a6e14..4dc4654 100644 (file)
@@ -592,3 +592,11 @@ Why:    In 3.0, we can now autodetect internal 3G device and already have
        interface that was used by acer-wmi driver. It will replaced by
        information log when acer-wmi initial.
 Who:    Lee, Chun-Yi <jlee@novell.com>
+
+----------------------------
+What:  The XFS nodelaylog mount option
+When:  3.3
+Why:   The delaylog mode that has been the default since 2.6.39 has proven
+       stable, and the old code is in the way of additional improvements in
+       the log code.
+Who:   Christoph Hellwig <hch@lst.de>
index 6e49c36..da45e6c 100644 (file)
@@ -27,7 +27,7 @@ His original code can still be found at:
 Does anyone know of a more current email address for Makoto? He doesn't
 respond to the address given above...
 
-Current maintainer: Sergey S. Kostyliov <rathamahata@php4.ru>
+This filesystem doesn't have a maintainer.
 
 WHAT IS THIS DRIVER?
 ==================
index 44b4f61..c11f64a 100644 (file)
@@ -62,6 +62,13 @@ can be safely used to identify the chip. You will have to instantiate
 the devices explicitly. Please see Documentation/i2c/instantiating-devices for
 details.
 
+WARNING: Do not access chip registers using the i2cdump command, and do not use
+any of the i2ctools commands on a command register (0xa5 to 0xac). The chips
+supported by this driver interpret any access to a command register (including
+read commands) as request to execute the command in question. This may result in
+power loss, board resets, and/or Flash corruption. Worst case, your board may
+turn into a brick.
+
 
 Sysfs entries
 -------------
index 845a191..54078ed 100644 (file)
@@ -319,4 +319,6 @@ Code  Seq#(hex)     Include File            Comments
                                        <mailto:thomas@winischhofer.net>
 0xF4   00-1F   video/mbxfb.h           mbxfb
                                        <mailto:raph@8d.com>
+0xF6   all     LTTng                   Linux Trace Toolkit Next Generation
+                                       <mailto:mathieu.desnoyers@efficios.com>
 0xFD   all     linux/dm-ioctl.h
index 9a86746..0e0734b 100644 (file)
        (including this document itself) have been moved there, and might
        be more up to date than the web version.
 
-     * Name: "Linux Source Driver"
-       URL: http://lsd.linux.cz
-       Keywords: Browsing source code.
-       Description: "Linux Source Driver (LSD) is an application, which
-       can make browsing source codes of Linux kernel easier than you can
-       imagine. You can select between multiple versions of kernel (e.g.
-       0.01, 1.0.0, 2.0.33, 2.0.34pre13, 2.0.0, 2.1.101 etc.). With LSD
-       you can search Linux kernel (fulltext, macros, types, functions
-       and variables) and LSD can generate patches for you on the fly
-       (files, directories or kernel)".
-
      * Name: "Linux Kernel Source Reference"
        Author: Thomas Graichen.
        URL: http://marc.info/?l=linux-kernel&m=96446640102205&w=4
index 78926aa..614d038 100644 (file)
@@ -40,6 +40,7 @@ parameter is applicable:
        ALSA    ALSA sound support is enabled.
        APIC    APIC support is enabled.
        APM     Advanced Power Management support is enabled.
+       ARM     ARM architecture is enabled.
        AVR32   AVR32 architecture is enabled.
        AX25    Appropriate AX.25 support is enabled.
        BLACKFIN Blackfin architecture is enabled.
@@ -49,6 +50,7 @@ parameter is applicable:
        EFI     EFI Partitioning (GPT) is enabled
        EIDE    EIDE/ATAPI support is enabled.
        FB      The frame buffer device is enabled.
+       FTRACE  Function tracing enabled.
        GCOV    GCOV profiling is enabled.
        HW      Appropriate hardware is enabled.
        IA-64   IA-64 architecture is enabled.
@@ -69,6 +71,7 @@ parameter is applicable:
                        Documentation/m68k/kernel-options.txt.
        MCA     MCA bus support is enabled.
        MDA     MDA console support is enabled.
+       MIPS    MIPS architecture is enabled.
        MOUSE   Appropriate mouse support is enabled.
        MSI     Message Signaled Interrupts (PCI).
        MTD     MTD (Memory Technology Device) support is enabled.
@@ -100,7 +103,6 @@ parameter is applicable:
        SPARC   Sparc architecture is enabled.
        SWSUSP  Software suspend (hibernation) is enabled.
        SUSPEND System suspend states are enabled.
-       FTRACE  Function tracing enabled.
        TPM     TPM drivers are enabled.
        TS      Appropriate touchscreen support is enabled.
        UMS     USB Mass Storage support is enabled.
@@ -115,7 +117,7 @@ parameter is applicable:
        X86-64  X86-64 architecture is enabled.
                        More X86-64 boot options can be found in
                        Documentation/x86/x86_64/boot-options.txt .
-       X86     Either 32bit or 64bit x86 (same as X86-32+X86-64)
+       X86     Either 32-bit or 64-bit x86 (same as X86-32+X86-64)
        XEN     Xen support is enabled
 
 In addition, the following text indicates that the option:
@@ -376,7 +378,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        atkbd.softrepeat= [HW]
                        Use software keyboard repeat
 
-       autotest        [IA64]
+       autotest        [IA-64]
 
        baycom_epp=     [HW,AX25]
                        Format: <io>,<mode>
@@ -681,8 +683,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                uart[8250],mmio32,<addr>[,options]
                        Start an early, polled-mode console on the 8250/16550
                        UART at the specified I/O port or MMIO address.
-                       MMIO inter-register address stride is either 8bit (mmio)
-                        or 32bit (mmio32).
+                       MMIO inter-register address stride is either 8-bit
+                       (mmio) or 32-bit (mmio32).
                        The options are the same as for ttyS, above.
 
        earlyprintk=    [X86,SH,BLACKFIN]
@@ -725,7 +727,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        See Documentation/block/as-iosched.txt and
                        Documentation/block/deadline-iosched.txt for details.
 
-       elfcorehdr=     [IA64,PPC,SH,X86]
+       elfcorehdr=     [IA-64,PPC,SH,X86]
                        Specifies physical address of start of kernel core
                        image elf header. Generally kexec loader will
                        pass this option to capture kernel.
@@ -791,7 +793,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        tracer at boot up. function-list is a comma separated
                        list of functions. This list can be changed at run
                        time by the set_ftrace_filter file in the debugfs
-                       tracing directory. 
+                       tracing directory.
 
        ftrace_notrace=[function-list]
                        [FTRACE] Do not trace the functions specified in
@@ -829,7 +831,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        hashdist=       [KNL,NUMA] Large hashes allocated during boot
                        are distributed across NUMA nodes.  Defaults on
-                       for 64bit NUMA, off otherwise.
+                       for 64-bit NUMA, off otherwise.
                        Format: 0 | 1 (for off | on)
 
        hcl=            [IA-64] SGI's Hardware Graph compatibility layer
@@ -998,10 +1000,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        DMA.
                forcedac [x86_64]
                        With this option iommu will not optimize to look
-                       for io virtual address below 32 bit forcing dual
+                       for io virtual address below 32-bit forcing dual
                        address cycle on pci bus for cards supporting greater
-                       than 32 bit addressing. The default is to look
-                       for translation below 32 bit and if not available
+                       than 32-bit addressing. The default is to look
+                       for translation below 32-bit and if not available
                        then look in the higher range.
                strict [Default Off]
                        With this option on every unmap_single operation will
@@ -1017,7 +1019,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        off     disable Interrupt Remapping
                        nosid   disable Source ID checking
 
-       inttest=        [IA64]
+       inttest=        [IA-64]
 
        iomem=          Disable strict checking of access to MMIO memory
                strict  regions from userspace.
@@ -1034,7 +1036,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                nomerge
                forcesac
                soft
-               pt      [x86, IA64]
+               pt      [x86, IA-64]
 
        io7=            [HW] IO7 for Marvel based alpha systems
                        See comment before marvel_specify_io7 in
@@ -1165,7 +1167,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        kvm-amd.npt=    [KVM,AMD] Disable nested paging (virtualized MMU)
                        for all guests.
-                       Default is 1 (enabled) if in 64bit or 32bit-PAE mode
+                       Default is 1 (enabled) if in 64-bit or 32-bit PAE mode.
 
        kvm-intel.ept=  [KVM,Intel] Disable extended page tables
                        (virtualized MMU) support on capable Intel chips.
@@ -1202,10 +1204,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        libata.dma=0      Disable all PATA and SATA DMA
                        libata.dma=1      PATA and SATA Disk DMA only
                        libata.dma=2      ATAPI (CDROM) DMA only
-                       libata.dma=4      Compact Flash DMA only 
+                       libata.dma=4      Compact Flash DMA only
                        Combinations also work, so libata.dma=3 enables DMA
                        for disks and CDROMs, but not CFs.
-       
+
        libata.ignore_hpa=      [LIBATA] Ignore HPA limit
                        libata.ignore_hpa=0       keep BIOS limits (default)
                        libata.ignore_hpa=1       ignore limits, using full disk
@@ -1331,7 +1333,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        ltpc=           [NET]
                        Format: <io>,<irq>,<dma>
 
-       machvec=        [IA64] Force the use of a particular machine-vector
+       machvec=        [IA-64] Force the use of a particular machine-vector
                        (machvec) in a generic kernel.
                        Example: machvec=hpzx1_swiotlb
 
@@ -1348,9 +1350,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        it is equivalent to "nosmp", which also disables
                        the IO APIC.
 
-       max_loop=       [LOOP] Maximum number of loopback devices that can
-                       be mounted
-                       Format: <1-256>
+       max_loop=       [LOOP] The number of loop block devices that get
+       (loop.max_loop) unconditionally pre-created at init time. The default
+                       number is configured by BLK_DEV_LOOP_MIN_COUNT. Instead
+                       of statically allocating a predefined number, loop
+                       devices can be requested on-demand with the
+                       /dev/loop-control interface.
 
        mcatest=        [IA-64]
 
@@ -1734,7 +1739,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        nointroute      [IA-64]
 
-       nojitter        [IA64] Disables jitter checking for ITC timers.
+       nojitter        [IA-64] Disables jitter checking for ITC timers.
 
        no-kvmclock     [X86,KVM] Disable paravirtualized KVM clock driver
 
@@ -1800,7 +1805,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        nox2apic        [X86-64,APIC] Do not enable x2APIC mode.
 
-       nptcg=          [IA64] Override max number of concurrent global TLB
+       nptcg=          [IA-64] Override max number of concurrent global TLB
                        purges which is reported from either PAL_VM_SUMMARY or
                        SAL PALO.
 
@@ -2077,7 +2082,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Format: { parport<nr> | timid | 0 }
                        See also Documentation/parport.txt.
 
-       pmtmr=          [X86] Manual setup of pmtmr I/O Port. 
+       pmtmr=          [X86] Manual setup of pmtmr I/O Port.
                        Override pmtimer IOPort with a hex value.
                        e.g. pmtmr=0x508
 
@@ -2635,6 +2640,16 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                        medium is write-protected).
                        Example: quirks=0419:aaf5:rl,0421:0433:rc
 
+       user_debug=     [KNL,ARM]
+                       Format: <int>
+                       See arch/arm/Kconfig.debug help text.
+                                1 - undefined instruction events
+                                2 - system calls
+                                4 - invalid data aborts
+                                8 - SIGSEGV faults
+                               16 - SIGBUS faults
+                       Example: user_debug=31
+
        userpte=
                        [X86] Flags controlling user PTE allocations.
 
index 4edd78d..bbce121 100644 (file)
@@ -1,13 +1,21 @@
 00-INDEX
        - this file
+3c359.txt
+       - information on the 3Com TokenLink Velocity XL (3c5359) driver.
 3c505.txt
        - information on the 3Com EtherLink Plus (3c505) driver.
+3c509.txt
+       - information on the 3Com Etherlink III Series Ethernet cards.
 6pack.txt
        - info on the 6pack protocol, an alternative to KISS for AX.25
 DLINK.txt
        - info on the D-Link DE-600/DE-620 parallel port pocket adapters
 PLIP.txt
        - PLIP: The Parallel Line Internet Protocol device driver
+README.ipw2100
+       - README for the Intel PRO/Wireless 2100 driver.
+README.ipw2200
+       - README for the Intel PRO/Wireless 2915ABG and 2200BG driver.
 README.sb1000
        - info on General Instrument/NextLevel SURFboard1000 cable modem.
 alias.txt
@@ -20,8 +28,12 @@ atm.txt
        - info on where to get ATM programs and support for Linux.
 ax25.txt
        - info on using AX.25 and NET/ROM code for Linux
+batman-adv.txt
+       - B.A.T.M.A.N routing protocol on top of layer 2 Ethernet Frames.
 baycom.txt
        - info on the driver for Baycom style amateur radio modems
+bonding.txt
+       - Linux Ethernet Bonding Driver HOWTO: link aggregation in Linux.
 bridge.txt
        - where to get user space programs for ethernet bridging with Linux.
 can.txt
@@ -34,32 +46,60 @@ cxacru.txt
        - Conexant AccessRunner USB ADSL Modem
 cxacru-cf.py
        - Conexant AccessRunner USB ADSL Modem configuration file parser
+cxgb.txt
+       - Release Notes for the Chelsio N210 Linux device driver.
+dccp.txt
+       - the Datagram Congestion Control Protocol (DCCP) (RFC 4340..42).
 de4x5.txt
        - the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
 decnet.txt
        - info on using the DECnet networking layer in Linux.
 depca.txt
        - the Digital DEPCA/EtherWORKS DE1?? and DE2?? LANCE Ethernet driver
+dl2k.txt
+       - README for D-Link DL2000-based Gigabit Ethernet Adapters (dl2k.ko).
+dm9000.txt
+       - README for the Simtec DM9000 Network driver.
 dmfe.txt
        - info on the Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver.
+dns_resolver.txt
+       - The DNS resolver module allows kernel servies to make DNS queries.
+driver.txt
+       - Softnet driver issues.
 e100.txt
        - info on Intel's EtherExpress PRO/100 line of 10/100 boards
 e1000.txt
        - info on Intel's E1000 line of gigabit ethernet boards
+e1000e.txt
+       - README for the Intel Gigabit Ethernet Driver (e1000e).
 eql.txt
        - serial IP load balancing
 ewrk3.txt
        - the Digital EtherWORKS 3 DE203/4/5 Ethernet driver
+fib_trie.txt
+       - Level Compressed Trie (LC-trie) notes: a structure for routing.
 filter.txt
        - Linux Socket Filtering
 fore200e.txt
        - FORE Systems PCA-200E/SBA-200E ATM NIC driver info.
 framerelay.txt
        - info on using Frame Relay/Data Link Connection Identifier (DLCI).
+gen_stats.txt
+       - Generic networking statistics for netlink users.
+generic_hdlc.txt
+       - The generic High Level Data Link Control (HDLC) layer.
 generic_netlink.txt
        - info on Generic Netlink
+gianfar.txt
+       - Gianfar Ethernet Driver.
 ieee802154.txt
        - Linux IEEE 802.15.4 implementation, API and drivers
+ifenslave.c
+       - Configure network interfaces for parallel routing (bonding).
+igb.txt
+       - README for the Intel Gigabit Ethernet Driver (igb).
+igbvf.txt
+       - README for the Intel Gigabit Ethernet Driver (igbvf).
 ip-sysctl.txt
        - /proc/sys/net/ipv4/* variables
 ip_dynaddr.txt
@@ -68,41 +108,117 @@ ipddp.txt
        - AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
 iphase.txt
        - Interphase PCI ATM (i)Chip IA Linux driver info.
+ipv6.txt
+       - Options to the ipv6 kernel module.
+ipvs-sysctl.txt
+       - Per-inode explanation of the /proc/sys/net/ipv4/vs interface.
 irda.txt
        - where to get IrDA (infrared) utilities and info for Linux.
+ixgb.txt
+       - README for the Intel 10 Gigabit Ethernet Driver (ixgb).
+ixgbe.txt
+       - README for the Intel 10 Gigabit Ethernet Driver (ixgbe).
+ixgbevf.txt
+       - README for the Intel Virtual Function (VF) Driver (ixgbevf).
+l2tp.txt
+       - User guide to the L2TP tunnel protocol.
 lapb-module.txt
        - programming information of the LAPB module.
 ltpc.txt
        - the Apple or Farallon LocalTalk PC card driver
+mac80211-injection.txt
+       - HOWTO use packet injection with mac80211
 multicast.txt
        - Behaviour of cards under Multicast
+multiqueue.txt
+       - HOWTO for multiqueue network device support.
+netconsole.txt
+       - The network console module netconsole.ko: configuration and notes.
+netdev-features.txt
+       - Network interface features API description.
 netdevices.txt
        - info on network device driver functions exported to the kernel.
+netif-msg.txt
+       - Design of the network interface message level setting (NETIF_MSG_*).
+nfc.txt
+       - The Linux Near Field Communication (NFS) subsystem.
 olympic.txt
        - IBM PCI Pit/Pit-Phy/Olympic Token Ring driver info.
+operstates.txt
+       - Overview of network interface operational states.
+packet_mmap.txt
+       - User guide to memory mapped packet socket rings (PACKET_[RT]X_RING).
+phonet.txt
+       - The Phonet packet protocol used in Nokia cellular modems.
+phy.txt
+       - The PHY abstraction layer.
+pktgen.txt
+       - User guide to the kernel packet generator (pktgen.ko).
 policy-routing.txt
        - IP policy-based routing
+ppp_generic.txt
+       - Information about the generic PPP driver.
+proc_net_tcp.txt
+       - Per inode overview of the /proc/net/tcp and /proc/net/tcp6 interfaces.
+radiotap-headers.txt
+       - Background on radiotap headers.
 ray_cs.txt
        - Raylink Wireless LAN card driver info.
+rds.txt
+       - Background on the reliable, ordered datagram delivery method RDS.
+regulatory.txt
+       - Overview of the Linux wireless regulatory infrastructure.
+rxrpc.txt
+       - Guide to the RxRPC protocol.
+s2io.txt
+       - Release notes for Neterion Xframe I/II 10GbE driver.
+scaling.txt
+       - Explanation of network scaling techniques: RSS, RPS, RFS, aRFS, XPS.
+sctp.txt
+       - Notes on the Linux kernel implementation of the SCTP protocol.
+secid.txt
+       - Explanation of the secid member in flow structures.
 skfp.txt
        - SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
 smc9.txt
        - the driver for SMC's 9000 series of Ethernet cards
 smctr.txt
        - SMC TokenCard TokenRing Linux driver info.
+spider-net.txt
+       - README for the Spidernet Driver (as found in PS3 / Cell BE).
+stmmac.txt
+       - README for the STMicro Synopsys Ethernet driver.
+tc-actions-env-rules.txt
+       - rules for traffic control (tc) actions.
+timestamping.txt
+       - overview of network packet timestamping variants.
 tcp.txt
        - short blurb on how TCP output takes place.
+tcp-thin.txt
+       - kernel tuning options for low rate 'thin' TCP streams.
 tlan.txt
        - ThunderLAN (Compaq Netelligent 10/100, Olicom OC-2xxx) driver info.
 tms380tr.txt
        - SysKonnect Token Ring ISA/PCI adapter driver info.
+tproxy.txt
+       - Transparent proxy support user guide.
 tuntap.txt
        - TUN/TAP device driver, allowing user space Rx/Tx of packets.
+udplite.txt
+       - UDP-Lite protocol (RFC 3828) introduction.
 vortex.txt
        - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
+vxge.txt
+       - README for the Neterion X3100 PCIe Server Adapter.
 x25.txt
        - general info on X.25 development.
 x25-iface.txt
        - description of the X.25 Packet Layer to LAPB device interface.
+xfrm_proc.txt
+       - description of the statistics package for XFRM.
+xfrm_sync.txt
+       - sync patches for XFRM enable migration of an SA between hosts.
+xfrm_sysctl.txt
+       - description of the XFRM configuration options.
 z8530drv.txt
        - info about Linux driver for Z8530 based HDLC cards for AX.25
index db2a406..8154699 100644 (file)
@@ -992,7 +992,7 @@ bindv6only - BOOLEAN
                TRUE: disable IPv4-mapped address feature
                FALSE: enable IPv4-mapped address feature
 
-       Default: FALSE (as specified in RFC2553bis)
+       Default: FALSE (as specified in RFC3493)
 
 IPv6 Fragmentation:
 
index 7254b4b..58fd741 100644 (file)
@@ -52,7 +52,8 @@ module parameter for specifying the number of hardware queues to
 configure. In the bnx2x driver, for instance, this parameter is called
 num_queues. A typical RSS configuration would be to have one receive queue
 for each CPU if the device supports enough queues, or otherwise at least
-one for each cache domain at a particular cache level (L1, L2, etc.).
+one for each memory domain, where a memory domain is a set of CPUs that
+share a particular memory level (L1, L2, NUMA node, etc.).
 
 The indirection table of an RSS device, which resolves a queue by masked
 hash, is usually programmed by the driver at initialization. The
@@ -82,11 +83,17 @@ RSS should be enabled when latency is a concern or whenever receive
 interrupt processing forms a bottleneck. Spreading load between CPUs
 decreases queue length. For low latency networking, the optimal setting
 is to allocate as many queues as there are CPUs in the system (or the
-NIC maximum, if lower). Because the aggregate number of interrupts grows
-with each additional queue, the most efficient high-rate configuration
+NIC maximum, if lower). The most efficient high-rate configuration
 is likely the one with the smallest number of receive queues where no
-CPU that processes receive interrupts reaches 100% utilization. Per-cpu
-load can be observed using the mpstat utility.
+receive queue overflows due to a saturated CPU, because in default
+mode with interrupt coalescing enabled, the aggregate number of
+interrupts (and thus work) grows with each additional queue.
+
+Per-cpu load can be observed using the mpstat utility, but note that on
+processors with hyperthreading (HT), each hyperthread is represented as
+a separate CPU. For interrupt handling, HT has shown no benefit in
+initial tests, so limit the number of queues to the number of CPU cores
+in the system.
 
 
 RPS: Receive Packet Steering
@@ -145,7 +152,7 @@ the bitmap.
 == Suggested Configuration
 
 For a single queue device, a typical RPS configuration would be to set
-the rps_cpus to the CPUs in the same cache domain of the interrupting
+the rps_cpus to the CPUs in the same memory domain of the interrupting
 CPU. If NUMA locality is not an issue, this could also be all CPUs in
 the system. At high interrupt rate, it might be wise to exclude the
 interrupting CPU from the map since that already performs much work.
@@ -154,7 +161,7 @@ For a multi-queue system, if RSS is configured so that a hardware
 receive queue is mapped to each CPU, then RPS is probably redundant
 and unnecessary. If there are fewer hardware queues than CPUs, then
 RPS might be beneficial if the rps_cpus for each queue are the ones that
-share the same cache domain as the interrupting CPU for that queue.
+share the same memory domain as the interrupting CPU for that queue.
 
 
 RFS: Receive Flow Steering
@@ -326,7 +333,7 @@ The queue chosen for transmitting a particular flow is saved in the
 corresponding socket structure for the flow (e.g. a TCP connection).
 This transmit queue is used for subsequent packets sent on the flow to
 prevent out of order (ooo) packets. The choice also amortizes the cost
-of calling get_xps_queues() over all packets in the connection. To avoid
+of calling get_xps_queues() over all packets in the flow. To avoid
 ooo packets, the queue for a flow can subsequently only be changed if
 skb->ooo_okay is set for a packet in the flow. This flag indicates that
 there are no outstanding packets in the flow, so the transmit queue can
index 4ce5450..6066e3a 100644 (file)
@@ -431,8 +431,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
 
   void pm_runtime_irq_safe(struct device *dev);
     - set the power.irq_safe flag for the device, causing the runtime-PM
-      suspend and resume callbacks (but not the idle callback) to be invoked
-      with interrupts disabled
+      callbacks to be invoked with interrupts off
 
   void pm_runtime_mark_last_busy(struct device *dev);
     - set the power.last_busy field to the current time
diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
new file mode 100644 (file)
index 0000000..8fb1ba7
--- /dev/null
@@ -0,0 +1,76 @@
+Ramoops oops/panic logger
+=========================
+
+Sergiu Iordache <sergiu@chromium.org>
+
+Updated: 8 August 2011
+
+0. Introduction
+
+Ramoops is an oops/panic logger that writes its logs to RAM before the system
+crashes. It works by logging oopses and panics in a circular buffer. Ramoops
+needs a system with persistent RAM so that the content of that area can
+survive after a restart.
+
+1. Ramoops concepts
+
+Ramoops uses a predefined memory area to store the dump. The start and size of
+the memory area are set using two variables:
+  * "mem_address" for the start
+  * "mem_size" for the size. The memory size will be rounded down to a
+  power of two.
+
+The memory area is divided into "record_size" chunks (also rounded down to
+power of two) and each oops/panic writes a "record_size" chunk of
+information.
+
+Dumping both oopses and panics can be done by setting 1 in the "dump_oops"
+variable while setting 0 in that variable dumps only the panics.
+
+The module uses a counter to record multiple dumps but the counter gets reset
+on restart (i.e. new dumps after the restart will overwrite old ones).
+
+2. Setting the parameters
+
+Setting the ramoops parameters can be done in 2 different manners:
+ 1. Use the module parameters (which have the names of the variables described
+ as before).
+ 2. Use a platform device and set the platform data. The parameters can then
+ be set through that platform data. An example of doing that is:
+
+#include <linux/ramoops.h>
+[...]
+
+static struct ramoops_platform_data ramoops_data = {
+        .mem_size               = <...>,
+        .mem_address            = <...>,
+        .record_size            = <...>,
+        .dump_oops              = <...>,
+};
+
+static struct platform_device ramoops_dev = {
+        .name = "ramoops",
+        .dev = {
+                .platform_data = &ramoops_data,
+        },
+};
+
+[... inside a function ...]
+int ret;
+
+ret = platform_device_register(&ramoops_dev);
+if (ret) {
+       printk(KERN_ERR "unable to register platform device\n");
+       return ret;
+}
+
+3. Dump format
+
+The data dump begins with a header, currently defined as "====" followed by a
+timestamp and a new line. The dump then continues with the actual data.
+
+4. Reading the data
+
+The dump data can be read from memory (through /dev/mem or other means).
+Getting the module parameters, which are needed in order to parse the data, can
+be done through /sys/module/ramoops/parameters/* .
index fe0251c..8e60199 100644 (file)
@@ -8,3 +8,6 @@ lguest/
        - Extremely simple hypervisor for experimental/educational use.
 uml/
        - User Mode Linux, builds/runs Linux kernel as a userspace program.
+virtio.txt
+       - Text version of draft virtio spec.
+          See http://ozlabs.org/~rusty/virtio-spec
index 043bd7d..d928c13 100644 (file)
@@ -1996,6 +1996,9 @@ int main(int argc, char *argv[])
        /* We use a simple helper to copy the arguments separated by spaces. */
        concat((char *)(boot + 1), argv+optind+2);
 
+       /* Set kernel alignment to 16M (CONFIG_PHYSICAL_ALIGN) */
+       boot->hdr.kernel_alignment = 0x1000000;
+
        /* Boot protocol version: 2.07 supports the fields for lguest. */
        boot->hdr.version = 0x207;
 
diff --git a/Documentation/virtual/virtio-spec.txt b/Documentation/virtual/virtio-spec.txt
new file mode 100644 (file)
index 0000000..a350ae1
--- /dev/null
@@ -0,0 +1,2200 @@
+[Generated file: see http://ozlabs.org/~rusty/virtio-spec/]
+Virtio PCI Card Specification
+v0.9.1 DRAFT
+-
+
+Rusty Russell <rusty@rustcorp.com.au>IBM Corporation (Editor)
+
+2011 August 1.
+
+Purpose and Description
+
+This document describes the specifications of the “virtio” family
+of PCI[LaTeX Command: nomenclature] devices. These are devices
+are found in virtual environments[LaTeX Command: nomenclature],
+yet by design they are not all that different from physical PCI
+devices, and this document treats them as such. This allows the
+guest to use standard PCI drivers and discovery mechanisms.
+
+The purpose of virtio and this specification is that virtual
+environments and guests should have a straightforward, efficient,
+standard and extensible mechanism for virtual devices, rather
+than boutique per-environment or per-OS mechanisms.
+
+  Straightforward: Virtio PCI devices use normal PCI mechanisms
+  of interrupts and DMA which should be familiar to any device
+  driver author. There is no exotic page-flipping or COW
+  mechanism: it's just a PCI device.[footnote:
+This lack of page-sharing implies that the implementation of the
+device (e.g. the hypervisor or host) needs full access to the
+guest memory. Communication with untrusted parties (i.e.
+inter-guest communication) requires copying.
+]
+
+  Efficient: Virtio PCI devices consist of rings of descriptors
+  for input and output, which are neatly separated to avoid cache
+  effects from both guest and device writing to the same cache
+  lines.
+
+  Standard: Virtio PCI makes no assumptions about the environment
+  in which it operates, beyond supporting PCI. In fact the virtio
+  devices specified in the appendices do not require PCI at all:
+  they have been implemented on non-PCI buses.[footnote:
+The Linux implementation further separates the PCI virtio code
+from the specific virtio drivers: these drivers are shared with
+the non-PCI implementations (currently lguest and S/390).
+]
+
+  Extensible: Virtio PCI devices contain feature bits which are
+  acknowledged by the guest operating system during device setup.
+  This allows forwards and backwards compatibility: the device
+  offers all the features it knows about, and the driver
+  acknowledges those it understands and wishes to use.
+
+  Virtqueues
+
+The mechanism for bulk data transport on virtio PCI devices is
+pretentiously called a virtqueue. Each device can have zero or
+more virtqueues: for example, the network device has one for
+transmit and one for receive.
+
+Each virtqueue occupies two or more physically-contiguous pages
+(defined, for the purposes of this specification, as 4096 bytes),
+and consists of three parts:
+
+
++-------------------+-----------------------------------+-----------+
+| Descriptor Table  |   Available Ring     (padding)    | Used Ring |
++-------------------+-----------------------------------+-----------+
+
+
+When the driver wants to send buffers to the device, it puts them
+in one or more slots in the descriptor table, and writes the
+descriptor indices into the available ring. It then notifies the
+device. When the device has finished with the buffers, it writes
+the descriptors into the used ring, and sends an interrupt.
+
+Specification
+
+  PCI Discovery
+
+Any PCI device with Vendor ID 0x1AF4, and Device ID 0x1000
+through 0x103F inclusive is a virtio device[footnote:
+The actual value within this range is ignored
+]. The device must also have a Revision ID of 0 to match this
+specification.
+
+The Subsystem Device ID indicates which virtio device is
+supported by the device. The Subsystem Vendor ID should reflect
+the PCI Vendor ID of the environment (it's currently only used
+for informational purposes by the guest).
+
+
++----------------------+--------------------+---------------+
+| Subsystem Device ID  |   Virtio Device    | Specification |
++----------------------+--------------------+---------------+
++----------------------+--------------------+---------------+
+|          1           |   network card     |  Appendix C   |
++----------------------+--------------------+---------------+
+|          2           |   block device     |  Appendix D   |
++----------------------+--------------------+---------------+
+|          3           |      console       |  Appendix E   |
++----------------------+--------------------+---------------+
+|          4           |  entropy source    |  Appendix F   |
++----------------------+--------------------+---------------+
+|          5           | memory ballooning  |  Appendix G   |
++----------------------+--------------------+---------------+
+|          6           |     ioMemory       |       -       |
++----------------------+--------------------+---------------+
+|          9           |   9P transport     |       -       |
++----------------------+--------------------+---------------+
+
+
+  Device Configuration
+
+To configure the device, we use the first I/O region of the PCI
+device. This contains a virtio header followed by a
+device-specific region.
+
+There may be different widths of accesses to the I/O region; the “
+natural” access method for each field in the virtio header must
+be used (i.e. 32-bit accesses for 32-bit fields, etc), but the
+device-specific region can be accessed using any width accesses,
+and should obtain the same results.
+
+Note that this is possible because while the virtio header is PCI
+(i.e. little) endian, the device-specific region is encoded in
+the native endian of the guest (where such distinction is
+applicable).
+
+  Device Initialization Sequence
+
+We start with an overview of device initialization, then expand
+on the details of the device and how each step is preformed.
+
+  Reset the device. This is not required on initial start up.
+
+  The ACKNOWLEDGE status bit is set: we have noticed the device.
+
+  The DRIVER status bit is set: we know how to drive the device.
+
+  Device-specific setup, including reading the Device Feature
+  Bits, discovery of virtqueues for the device, optional MSI-X
+  setup, and reading and possibly writing the virtio
+  configuration space.
+
+  The subset of Device Feature Bits understood by the driver is
+  written to the device.
+
+  The DRIVER_OK status bit is set.
+
+  The device can now be used (ie. buffers added to the
+  virtqueues)[footnote:
+Historically, drivers have used the device before steps 5 and 6.
+This is only allowed if the driver does not use any features
+which would alter this early use of the device.
+]
+
+If any of these steps go irrecoverably wrong, the guest should
+set the FAILED status bit to indicate that it has given up on the
+device (it can reset the device later to restart if desired).
+
+We now cover the fields required for general setup in detail.
+
+  Virtio Header
+
+The virtio header looks as follows:
+
+
++------------++---------------------+---------------------+----------+--------+---------+---------+---------+--------+
+| Bits       || 32                  | 32                  | 32       | 16     | 16      | 16      | 8       | 8      |
++------------++---------------------+---------------------+----------+--------+---------+---------+---------+--------+
+| Read/Write || R                   | R+W                 | R+W      | R      | R+W     | R+W     | R+W     | R      |
++------------++---------------------+---------------------+----------+--------+---------+---------+---------+--------+
+| Purpose    || Device              | Guest               | Queue    | Queue  | Queue   | Queue   | Device  | ISR    |
+|            || Features bits 0:31  | Features bits 0:31  | Address  | Size   | Select  | Notify  | Status  | Status |
++------------++---------------------+---------------------+----------+--------+---------+---------+---------+--------+
+
+
+If MSI-X is enabled for the device, two additional fields
+immediately follow this header:
+
+
++------------++----------------+--------+
+| Bits       || 16             | 16     |
+              +----------------+--------+
++------------++----------------+--------+
+| Read/Write || R+W            | R+W    |
++------------++----------------+--------+
+| Purpose    || Configuration  | Queue  |
+| (MSI-X)    || Vector         | Vector |
++------------++----------------+--------+
+
+
+Finally, if feature bits (VIRTIO_F_FEATURES_HI) this is
+immediately followed by two additional fields:
+
+
++------------++----------------------+----------------------
+| Bits       || 32                   | 32
++------------++----------------------+----------------------
+| Read/Write || R                    | R+W
++------------++----------------------+----------------------
+| Purpose    || Device               | Guest
+|            || Features bits 32:63  | Features bits 32:63
++------------++----------------------+----------------------
+
+
+Immediately following these general headers, there may be
+device-specific headers:
+
+
++------------++--------------------+
+| Bits       || Device Specific    |
+              +--------------------+
++------------++--------------------+
+| Read/Write || Device Specific    |
++------------++--------------------+
+| Purpose    || Device Specific... |
+|            ||                    |
++------------++--------------------+
+
+
+  Device Status
+
+The Device Status field is updated by the guest to indicate its
+progress. This provides a simple low-level diagnostic: it's most
+useful to imagine them hooked up to traffic lights on the console
+indicating the status of each device.
+
+The device can be reset by writing a 0 to this field, otherwise
+at least one bit should be set:
+
+  ACKNOWLEDGE (1) Indicates that the guest OS has found the
+  device and recognized it as a valid virtio device.
+
+  DRIVER (2) Indicates that the guest OS knows how to drive the
+  device. Under Linux, drivers can be loadable modules so there
+  may be a significant (or infinite) delay before setting this
+  bit.
+
+  DRIVER_OK (3) Indicates that the driver is set up and ready to
+  drive the device.
+
+  FAILED (8) Indicates that something went wrong in the guest,
+  and it has given up on the device. This could be an internal
+  error, or the driver didn't like the device for some reason, or
+  even a fatal error during device operation. The device must be
+  reset before attempting to re-initialize.
+
+  Feature Bits
+
+The least significant 31 bits of the first configuration field
+indicates the features that the device supports (the high bit is
+reserved, and will be used to indicate the presence of future
+feature bits elsewhere). If more than 31 feature bits are
+supported, the device indicates so by setting feature bit 31 (see
+[cha:Reserved-Feature-Bits]). The bits are allocated as follows:
+
+  0 to 23 Feature bits for the specific device type
+
+  24 to 40 Feature bits reserved for extensions to the queue and
+  feature negotiation mechanisms
+
+  41 to 63 Feature bits reserved for future extensions
+
+For example, feature bit 0 for a network device (i.e. Subsystem
+Device ID 1) indicates that the device supports checksumming of
+packets.
+
+The feature bits are negotiated: the device lists all the
+features it understands in the Device Features field, and the
+guest writes the subset that it understands into the Guest
+Features field. The only way to renegotiate is to reset the
+device.
+
+In particular, new fields in the device configuration header are
+indicated by offering a feature bit, so the guest can check
+before accessing that part of the configuration space.
+
+This allows for forwards and backwards compatibility: if the
+device is enhanced with a new feature bit, older guests will not
+write that feature bit back to the Guest Features field and it
+can go into backwards compatibility mode. Similarly, if a guest
+is enhanced with a feature that the device doesn't support, it
+will not see that feature bit in the Device Features field and
+can go into backwards compatibility mode (or, for poor
+implementations, set the FAILED Device Status bit).
+
+Access to feature bits 32 to 63 is enabled by Guest by setting
+feature bit 31. If this bit is unset, Device must assume that all
+feature bits > 31 are unset.
+
+  Configuration/Queue Vectors
+
+When MSI-X capability is present and enabled in the device
+(through standard PCI configuration space) 4 bytes at byte offset
+20 are used to map configuration change and queue interrupts to
+MSI-X vectors. In this case, the ISR Status field is unused, and
+device specific configuration starts at byte offset 24 in virtio
+header structure. When MSI-X capability is not enabled, device
+specific configuration starts at byte offset 20 in virtio header.
+
+Writing a valid MSI-X Table entry number, 0 to 0x7FF, to one of
+Configuration/Queue Vector registers, maps interrupts triggered
+by the configuration change/selected queue events respectively to
+the corresponding MSI-X vector. To disable interrupts for a
+specific event type, unmap it by writing a special NO_VECTOR
+value:
+
+/* Vector value used to disable MSI for queue */
+
+#define VIRTIO_MSI_NO_VECTOR            0xffff
+
+Reading these registers returns vector mapped to a given event,
+or NO_VECTOR if unmapped. All queue and configuration change
+events are unmapped by default.
+
+Note that mapping an event to vector might require allocating
+internal device resources, and might fail. Devices report such
+failures by returning the NO_VECTOR value when the relevant
+Vector field is read. After mapping an event to vector, the
+driver must verify success by reading the Vector field value: on
+success, the previously written value is returned, and on
+failure, NO_VECTOR is returned. If a mapping failure is detected,
+the driver can retry mapping with fewervectors, or disable MSI-X.
+
+  Virtqueue Configuration
+
+As a device can have zero or more virtqueues for bulk data
+transport (for example, the network driver has two), the driver
+needs to configure them as part of the device-specific
+configuration.
+
+This is done as follows, for each virtqueue a device has:
+
+  Write the virtqueue index (first queue is 0) to the Queue
+  Select field.
+
+  Read the virtqueue size from the Queue Size field, which is
+  always a power of 2. This controls how big the virtqueue is
+  (see below). If this field is 0, the virtqueue does not exist.
+
+  Allocate and zero virtqueue in contiguous physical memory, on a
+  4096 byte alignment. Write the physical address, divided by
+  4096 to the Queue Address field.[footnote:
+The 4096 is based on the x86 page size, but it's also large
+enough to ensure that the separate parts of the virtqueue are on
+separate cache lines.
+]
+
+  Optionally, if MSI-X capability is present and enabled on the
+  device, select a vector to use to request interrupts triggered
+  by virtqueue events. Write the MSI-X Table entry number
+  corresponding to this vector in Queue Vector field. Read the
+  Queue Vector field: on success, previously written value is
+  returned; on failure, NO_VECTOR value is returned.
+
+The Queue Size field controls the total number of bytes required
+for the virtqueue according to the following formula:
+
+#define ALIGN(x) (((x) + 4095) & ~4095)
+
+static inline unsigned vring_size(unsigned int qsz)
+
+{
+
+     return ALIGN(sizeof(struct vring_desc)*qsz + sizeof(u16)*(2
++ qsz))
+
+          + ALIGN(sizeof(struct vring_used_elem)*qsz);
+
+}
+
+This currently wastes some space with padding, but also allows
+future extensions. The virtqueue layout structure looks like this
+(qsz is the Queue Size field, which is a variable, so this code
+won't compile):
+
+struct vring {
+
+    /* The actual descriptors (16 bytes each) */
+
+    struct vring_desc desc[qsz];
+
+
+
+    /* A ring of available descriptor heads with free-running
+index. */
+
+    struct vring_avail avail;
+
+
+
+    // Padding to the next 4096 boundary.
+
+    char pad[];
+
+
+
+    // A ring of used descriptor heads with free-running index.
+
+    struct vring_used used;
+
+};
+
+  A Note on Virtqueue Endianness
+
+Note that the endian of these fields and everything else in the
+virtqueue is the native endian of the guest, not little-endian as
+PCI normally is. This makes for simpler guest code, and it is
+assumed that the host already has to be deeply aware of the guest
+endian so such an “endian-aware” device is not a significant
+issue.
+
+  Descriptor Table
+
+The descriptor table refers to the buffers the guest is using for
+the device. The addresses are physical addresses, and the buffers
+can be chained via the next field. Each descriptor describes a
+buffer which is read-only or write-only, but a chain of
+descriptors can contain both read-only and write-only buffers.
+
+No descriptor chain may be more than 2^32 bytes long in total.struct vring_desc {
+
+    /* Address (guest-physical). */
+
+    u64 addr;
+
+    /* Length. */
+
+    u32 len;
+
+/* This marks a buffer as continuing via the next field. */
+
+#define VRING_DESC_F_NEXT   1
+
+/* This marks a buffer as write-only (otherwise read-only). */
+
+#define VRING_DESC_F_WRITE     2
+
+/* This means the buffer contains a list of buffer descriptors.
+*/
+
+#define VRING_DESC_F_INDIRECT   4
+
+    /* The flags as indicated above. */
+
+    u16 flags;
+
+    /* Next field if flags & NEXT */
+
+    u16 next;
+
+};
+
+The number of descriptors in the table is specified by the Queue
+Size field for this virtqueue.
+
+  <sub:Indirect-Descriptors>Indirect Descriptors
+
+Some devices benefit by concurrently dispatching a large number
+of large requests. The VIRTIO_RING_F_INDIRECT_DESC feature can be
+used to allow this (see [cha:Reserved-Feature-Bits]). To increase
+ring capacity it is possible to store a table of indirect
+descriptors anywhere in memory, and insert a descriptor in main
+virtqueue (with flags&INDIRECT on) that refers to memory buffer
+containing this indirect descriptor table; fields addr and len
+refer to the indirect table address and length in bytes,
+respectively. The indirect table layout structure looks like this
+(len is the length of the descriptor that refers to this table,
+which is a variable, so this code won't compile):
+
+struct indirect_descriptor_table {
+
+    /* The actual descriptors (16 bytes each) */
+
+    struct vring_desc desc[len / 16];
+
+};
+
+The first indirect descriptor is located at start of the indirect
+descriptor table (index 0), additional indirect descriptors are
+chained by next field. An indirect descriptor without next field
+(with flags&NEXT off) signals the end of the indirect descriptor
+table, and transfers control back to the main virtqueue. An
+indirect descriptor can not refer to another indirect descriptor
+table (flags&INDIRECT must be off). A single indirect descriptor
+table can include both read-only and write-only descriptors;
+write-only flag (flags&WRITE) in the descriptor that refers to it
+is ignored.
+
+  Available Ring
+
+The available ring refers to what descriptors we are offering the
+device: it refers to the head of a descriptor chain. The “flags”
+field is currently 0 or 1: 1 indicating that we do not need an
+interrupt when the device consumes a descriptor from the
+available ring. Alternatively, the guest can ask the device to
+delay interrupts until an entry with an index specified by the “
+used_event” field is written in the used ring (equivalently,
+until the idx field in the used ring will reach the value
+used_event + 1). The method employed by the device is controlled
+by the VIRTIO_RING_F_EVENT_IDX feature bit (see [cha:Reserved-Feature-Bits]
+). This interrupt suppression is merely an optimization; it may
+not suppress interrupts entirely.
+
+The “idx” field indicates where we would put the next descriptor
+entry (modulo the ring size). This starts at 0, and increases.
+
+struct vring_avail {
+
+#define VRING_AVAIL_F_NO_INTERRUPT      1
+
+   u16 flags;
+
+   u16 idx;
+
+   u16 ring[qsz]; /* qsz is the Queue Size field read from device
+*/
+
+   u16 used_event;
+
+};
+
+  Used Ring
+
+The used ring is where the device returns buffers once it is done
+with them. The flags field can be used by the device to hint that
+no notification is necessary when the guest adds to the available
+ring. Alternatively, the “avail_event” field can be used by the
+device to hint that no notification is necessary until an entry
+with an index specified by the “avail_event” is written in the
+available ring (equivalently, until the idx field in the
+available ring will reach the value avail_event + 1). The method
+employed by the device is controlled by the guest through the
+VIRTIO_RING_F_EVENT_IDX feature bit (see [cha:Reserved-Feature-Bits]
+). [footnote:
+These fields are kept here because this is the only part of the
+virtqueue written by the device
+].
+
+Each entry in the ring is a pair: the head entry of the
+descriptor chain describing the buffer (this matches an entry
+placed in the available ring by the guest earlier), and the total
+of bytes written into the buffer. The latter is extremely useful
+for guests using untrusted buffers: if you do not know exactly
+how much has been written by the device, you usually have to zero
+the buffer to ensure no data leakage occurs.
+
+/* u32 is used here for ids for padding reasons. */
+
+struct vring_used_elem {
+
+    /* Index of start of used descriptor chain. */
+
+    u32 id;
+
+    /* Total length of the descriptor chain which was used
+(written to) */
+
+    u32 len;
+
+};
+
+
+
+struct vring_used {
+
+#define VRING_USED_F_NO_NOTIFY  1
+
+    u16 flags;
+
+    u16 idx;
+
+    struct vring_used_elem ring[qsz];
+
+    u16 avail_event;
+
+};
+
+  Helpers for Managing Virtqueues
+
+The Linux Kernel Source code contains the definitions above and
+helper routines in a more usable form, in
+include/linux/virtio_ring.h. This was explicitly licensed by IBM
+and Red Hat under the (3-clause) BSD license so that it can be
+freely used by all other projects, and is reproduced (with slight
+variation to remove Linux assumptions) in Appendix A.
+
+  Device Operation
+
+There are two parts to device operation: supplying new buffers to
+the device, and processing used buffers from the device. As an
+example, the virtio network device has two virtqueues: the
+transmit virtqueue and the receive virtqueue. The driver adds
+outgoing (read-only) packets to the transmit virtqueue, and then
+frees them after they are used. Similarly, incoming (write-only)
+buffers are added to the receive virtqueue, and processed after
+they are used.
+
+  Supplying Buffers to The Device
+
+Actual transfer of buffers from the guest OS to the device
+operates as follows:
+
+  Place the buffer(s) into free descriptor(s).
+
+  If there are no free descriptors, the guest may choose to
+    notify the device even if notifications are suppressed (to
+    reduce latency).[footnote:
+The Linux drivers do this only for read-only buffers: for
+write-only buffers, it is assumed that the driver is merely
+trying to keep the receive buffer ring full, and no notification
+of this expected condition is necessary.
+]
+
+  Place the id of the buffer in the next ring entry of the
+  available ring.
+
+  The steps (1) and (2) may be performed repeatedly if batching
+  is possible.
+
+  A memory barrier should be executed to ensure the device sees
+  the updated descriptor table and available ring before the next
+  step.
+
+  The available “idx” field should be increased by the number of
+  entries added to the available ring.
+
+  A memory barrier should be executed to ensure that we update
+  the idx field before checking for notification suppression.
+
+  If notifications are not suppressed, the device should be
+  notified of the new buffers.
+
+Note that the above code does not take precautions against the
+available ring buffer wrapping around: this is not possible since
+the ring buffer is the same size as the descriptor table, so step
+(1) will prevent such a condition.
+
+In addition, the maximum queue size is 32768 (it must be a power
+of 2 which fits in 16 bits), so the 16-bit “idx” value can always
+distinguish between a full and empty buffer.
+
+Here is a description of each stage in more detail.
+
+  Placing Buffers Into The Descriptor Table
+
+A buffer consists of zero or more read-only physically-contiguous
+elements followed by zero or more physically-contiguous
+write-only elements (it must have at least one element). This
+algorithm maps it into the descriptor table:
+
+  for each buffer element, b:
+
+  Get the next free descriptor table entry, d
+
+  Set d.addr to the physical address of the start of b
+
+  Set d.len to the length of b.
+
+  If b is write-only, set d.flags to VRING_DESC_F_WRITE,
+    otherwise 0.
+
+  If there is a buffer element after this:
+
+    Set d.next to the index of the next free descriptor element.
+
+    Set the VRING_DESC_F_NEXT bit in d.flags.
+
+In practice, the d.next fields are usually used to chain free
+descriptors, and a separate count kept to check there are enough
+free descriptors before beginning the mappings.
+
+  Updating The Available Ring
+
+The head of the buffer we mapped is the first d in the algorithm
+above. A naive implementation would do the following:
+
+avail->ring[avail->idx % qsz] = head;
+
+However, in general we can add many descriptors before we update
+the “idx” field (at which point they become visible to the
+device), so we keep a counter of how many we've added:
+
+avail->ring[(avail->idx + added++) % qsz] = head;
+
+  Updating The Index Field
+
+Once the idx field of the virtqueue is updated, the device will
+be able to access the descriptor entries we've created and the
+memory they refer to. This is why a memory barrier is generally
+used before the idx update, to ensure it sees the most up-to-date
+copy.
+
+The idx field always increments, and we let it wrap naturally at
+65536:
+
+avail->idx += added;
+
+  <sub:Notifying-The-Device>Notifying The Device
+
+Device notification occurs by writing the 16-bit virtqueue index
+of this virtqueue to the Queue Notify field of the virtio header
+in the first I/O region of the PCI device. This can be expensive,
+however, so the device can suppress such notifications if it
+doesn't need them. We have to be careful to expose the new idx
+value before checking the suppression flag: it's OK to notify
+gratuitously, but not to omit a required notification. So again,
+we use a memory barrier here before reading the flags or the
+avail_event field.
+
+If the VIRTIO_F_RING_EVENT_IDX feature is not negotiated, and if
+the VRING_USED_F_NOTIFY flag is not set, we go ahead and write to
+the PCI configuration space.
+
+If the VIRTIO_F_RING_EVENT_IDX feature is negotiated, we read the
+avail_event field in the available ring structure. If the
+available index crossed_the avail_event field value since the
+last notification, we go ahead and write to the PCI configuration
+space. The avail_event field wraps naturally at 65536 as well:
+
+(u16)(new_idx - avail_event - 1) < (u16)(new_idx - old_idx)
+
+  <sub:Receiving-Used-Buffers>Receiving Used Buffers From The
+  Device
+
+Once the device has used a buffer (read from or written to it, or
+parts of both, depending on the nature of the virtqueue and the
+device), it sends an interrupt, following an algorithm very
+similar to the algorithm used for the driver to send the device a
+buffer:
+
+  Write the head descriptor number to the next field in the used
+  ring.
+
+  Update the used ring idx.
+
+  Determine whether an interrupt is necessary:
+
+  If the VIRTIO_F_RING_EVENT_IDX feature is not negotiated: check
+    if f the VRING_AVAIL_F_NO_INTERRUPT flag is not set in avail-
+    >flags
+
+  If the VIRTIO_F_RING_EVENT_IDX feature is negotiated: check
+    whether the used index crossed the used_event field value
+    since the last update. The used_event field wraps naturally
+    at 65536 as well:(u16)(new_idx - used_event - 1) < (u16)(new_idx - old_idx)
+
+  If an interrupt is necessary:
+
+  If MSI-X capability is disabled:
+
+    Set the lower bit of the ISR Status field for the device.
+
+    Send the appropriate PCI interrupt for the device.
+
+  If MSI-X capability is enabled:
+
+    Request the appropriate MSI-X interrupt message for the
+      device, Queue Vector field sets the MSI-X Table entry
+      number.
+
+    If Queue Vector field value is NO_VECTOR, no interrupt
+      message is requested for this event.
+
+The guest interrupt handler should:
+
+  If MSI-X capability is disabled: read the ISR Status field,
+  which will reset it to zero. If the lower bit is zero, the
+  interrupt was not for this device. Otherwise, the guest driver
+  should look through the used rings of each virtqueue for the
+  device, to see if any progress has been made by the device
+  which requires servicing.
+
+  If MSI-X capability is enabled: look through the used rings of
+  each virtqueue mapped to the specific MSI-X vector for the
+  device, to see if any progress has been made by the device
+  which requires servicing.
+
+For each ring, guest should then disable interrupts by writing
+VRING_AVAIL_F_NO_INTERRUPT flag in avail structure, if required.
+It can then process used ring entries finally enabling interrupts
+by clearing the VRING_AVAIL_F_NO_INTERRUPT flag or updating the
+EVENT_IDX field in the available structure, Guest should then
+execute a memory barrier, and then recheck the ring empty
+condition. This is necessary to handle the case where, after the
+last check and before enabling interrupts, an interrupt has been
+suppressed by the device:
+
+vring_disable_interrupts(vq);
+
+for (;;) {
+
+    if (vq->last_seen_used != vring->used.idx) {
+
+               vring_enable_interrupts(vq);
+
+               mb();
+
+               if (vq->last_seen_used != vring->used.idx)
+
+                       break;
+
+    }
+
+    struct vring_used_elem *e =
+vring.used->ring[vq->last_seen_used%vsz];
+
+    process_buffer(e);
+
+    vq->last_seen_used++;
+
+}
+
+  Dealing With Configuration Changes
+
+Some virtio PCI devices can change the device configuration
+state, as reflected in the virtio header in the PCI configuration
+space. In this case:
+
+  If MSI-X capability is disabled: an interrupt is delivered and
+  the second highest bit is set in the ISR Status field to
+  indicate that the driver should re-examine the configuration
+  space.Note that a single interrupt can indicate both that one
+  or more virtqueue has been used and that the configuration
+  space has changed: even if the config bit is set, virtqueues
+  must be scanned.
+
+  If MSI-X capability is enabled: an interrupt message is
+  requested. The Configuration Vector field sets the MSI-X Table
+  entry number to use. If Configuration Vector field value is
+  NO_VECTOR, no interrupt message is requested for this event.
+
+Creating New Device Types
+
+Various considerations are necessary when creating a new device
+type:
+
+  How Many Virtqueues?
+
+It is possible that a very simple device will operate entirely
+through its configuration space, but most will need at least one
+virtqueue in which it will place requests. A device with both
+input and output (eg. console and network devices described here)
+need two queues: one which the driver fills with buffers to
+receive input, and one which the driver places buffers to
+transmit output.
+
+  What Configuration Space Layout?
+
+Configuration space is generally used for rarely-changing or
+initialization-time parameters. But it is a limited resource, so
+it might be better to use a virtqueue to update configuration
+information (the network device does this for filtering,
+otherwise the table in the config space could potentially be very
+large).
+
+Note that this space is generally the guest's native endian,
+rather than PCI's little-endian.
+
+  What Device Number?
+
+Currently device numbers are assigned quite freely: a simple
+request mail to the author of this document or the Linux
+virtualization mailing list[footnote:
+
+https://lists.linux-foundation.org/mailman/listinfo/virtualization
+] will be sufficient to secure a unique one.
+
+Meanwhile for experimental drivers, use 65535 and work backwards.
+
+  How many MSI-X vectors?
+
+Using the optional MSI-X capability devices can speed up
+interrupt processing by removing the need to read ISR Status
+register by guest driver (which might be an expensive operation),
+reducing interrupt sharing between devices and queues within the
+device, and handling interrupts from multiple CPUs. However, some
+systems impose a limit (which might be as low as 256) on the
+total number of MSI-X vectors that can be allocated to all
+devices. Devices and/or device drivers should take this into
+account, limiting the number of vectors used unless the device is
+expected to cause a high volume of interrupts. Devices can
+control the number of vectors used by limiting the MSI-X Table
+Size or not presenting MSI-X capability in PCI configuration
+space. Drivers can control this by mapping events to as small
+number of vectors as possible, or disabling MSI-X capability
+altogether.
+
+  Message Framing
+
+The descriptors used for a buffer should not effect the semantics
+of the message, except for the total length of the buffer. For
+example, a network buffer consists of a 10 byte header followed
+by the network packet. Whether this is presented in the ring
+descriptor chain as (say) a 10 byte buffer and a 1514 byte
+buffer, or a single 1524 byte buffer, or even three buffers,
+should have no effect.
+
+In particular, no implementation should use the descriptor
+boundaries to determine the size of any header in a request.[footnote:
+The current qemu device implementations mistakenly insist that
+the first descriptor cover the header in these cases exactly, so
+a cautious driver should arrange it so.
+]
+
+  Device Improvements
+
+Any change to configuration space, or new virtqueues, or
+behavioural changes, should be indicated by negotiation of a new
+feature bit. This establishes clarity[footnote:
+Even if it does mean documenting design or implementation
+mistakes!
+] and avoids future expansion problems.
+
+Clusters of functionality which are always implemented together
+can use a single bit, but if one feature makes sense without the
+others they should not be gratuitously grouped together to
+conserve feature bits. We can always extend the spec when the
+first person needs more than 24 feature bits for their device.
+
+[LaTeX Command: printnomenclature]
+
+Appendix A: virtio_ring.h
+
+#ifndef VIRTIO_RING_H
+
+#define VIRTIO_RING_H
+
+/* An interface for efficient virtio implementation.
+
+ *
+
+ * This header is BSD licensed so anyone can use the definitions
+
+ * to implement compatible drivers/servers.
+
+ *
+
+ * Copyright 2007, 2009, IBM Corporation
+
+ * Copyright 2011, Red Hat, Inc
+
+ * All rights reserved.
+
+ *
+
+ * Redistribution and use in source and binary forms, with or
+without
+
+ * modification, are permitted provided that the following
+conditions
+
+ * are met:
+
+ * 1. Redistributions of source code must retain the above
+copyright
+
+ *    notice, this list of conditions and the following
+disclaimer.
+
+ * 2. Redistributions in binary form must reproduce the above
+copyright
+
+ *    notice, this list of conditions and the following
+disclaimer in the
+
+ *    documentation and/or other materials provided with the
+distribution.
+
+ * 3. Neither the name of IBM nor the names of its contributors
+
+ *    may be used to endorse or promote products derived from
+this software
+
+ *    without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ``AS IS'' AND
+
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE
+
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE
+
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE
+LIABLE
+
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL
+
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS
+
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION)
+
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT
+
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY
+
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF
+
+ * SUCH DAMAGE.
+
+ */
+
+
+
+/* This marks a buffer as continuing via the next field. */
+
+#define VRING_DESC_F_NEXT       1
+
+/* This marks a buffer as write-only (otherwise read-only). */
+
+#define VRING_DESC_F_WRITE      2
+
+
+
+/* The Host uses this in used->flags to advise the Guest: don't
+kick me
+
+ * when you add a buffer.  It's unreliable, so it's simply an
+
+ * optimization.  Guest will still kick if it's out of buffers.
+*/
+
+#define VRING_USED_F_NO_NOTIFY  1
+
+/* The Guest uses this in avail->flags to advise the Host: don't
+
+ * interrupt me when you consume a buffer.  It's unreliable, so
+it's
+
+ * simply an optimization.  */
+
+#define VRING_AVAIL_F_NO_INTERRUPT      1
+
+
+
+/* Virtio ring descriptors: 16 bytes.
+
+ * These can chain together via "next". */
+
+struct vring_desc {
+
+        /* Address (guest-physical). */
+
+        uint64_t addr;
+
+        /* Length. */
+
+        uint32_t len;
+
+        /* The flags as indicated above. */
+
+        uint16_t flags;
+
+        /* We chain unused descriptors via this, too */
+
+        uint16_t next;
+
+};
+
+
+
+struct vring_avail {
+
+        uint16_t flags;
+
+        uint16_t idx;
+
+        uint16_t ring[];
+
+        uint16_t used_event;
+
+};
+
+
+
+/* u32 is used here for ids for padding reasons. */
+
+struct vring_used_elem {
+
+        /* Index of start of used descriptor chain. */
+
+        uint32_t id;
+
+        /* Total length of the descriptor chain which was written
+to. */
+
+        uint32_t len;
+
+};
+
+
+
+struct vring_used {
+
+        uint16_t flags;
+
+        uint16_t idx;
+
+        struct vring_used_elem ring[];
+
+        uint16_t avail_event;
+
+};
+
+
+
+struct vring {
+
+        unsigned int num;
+
+
+
+        struct vring_desc *desc;
+
+        struct vring_avail *avail;
+
+        struct vring_used *used;
+
+};
+
+
+
+/* The standard layout for the ring is a continuous chunk of
+memory which
+
+ * looks like this.  We assume num is a power of 2.
+
+ *
+
+ * struct vring {
+
+ *      // The actual descriptors (16 bytes each)
+
+ *      struct vring_desc desc[num];
+
+ *
+
+ *      // A ring of available descriptor heads with free-running
+index.
+
+ *      __u16 avail_flags;
+
+ *      __u16 avail_idx;
+
+ *      __u16 available[num];
+
+ *
+
+ *      // Padding to the next align boundary.
+
+ *      char pad[];
+
+ *
+
+ *      // A ring of used descriptor heads with free-running
+index.
+
+ *      __u16 used_flags;
+
+ *      __u16 EVENT_IDX;
+
+ *      struct vring_used_elem used[num];
+
+ * };
+
+ * Note: for virtio PCI, align is 4096.
+
+ */
+
+static inline void vring_init(struct vring *vr, unsigned int num,
+void *p,
+
+                              unsigned long align)
+
+{
+
+        vr->num = num;
+
+        vr->desc = p;
+
+        vr->avail = p + num*sizeof(struct vring_desc);
+
+        vr->used = (void *)(((unsigned long)&vr->avail->ring[num]
+
+                              + align-1)
+
+                            & ~(align - 1));
+
+}
+
+
+
+static inline unsigned vring_size(unsigned int num, unsigned long
+align)
+
+{
+
+        return ((sizeof(struct vring_desc)*num +
+sizeof(uint16_t)*(2+num)
+
+                 + align - 1) & ~(align - 1))
+
+                + sizeof(uint16_t)*3 + sizeof(struct
+vring_used_elem)*num;
+
+}
+
+
+
+static inline int vring_need_event(uint16_t event_idx, uint16_t
+new_idx, uint16_t old_idx)
+
+{
+
+         return (uint16_t)(new_idx - event_idx - 1) <
+(uint16_t)(new_idx - old_idx);
+
+}
+
+#endif /* VIRTIO_RING_H */
+
+<cha:Reserved-Feature-Bits>Appendix B: Reserved Feature Bits
+
+Currently there are five device-independent feature bits defined:
+
+  VIRTIO_F_NOTIFY_ON_EMPTY (24) Negotiating this feature
+  indicates that the driver wants an interrupt if the device runs
+  out of available descriptors on a virtqueue, even though
+  interrupts are suppressed using the VRING_AVAIL_F_NO_INTERRUPT
+  flag or the used_event field. An example of this is the
+  networking driver: it doesn't need to know every time a packet
+  is transmitted, but it does need to free the transmitted
+  packets a finite time after they are transmitted. It can avoid
+  using a timer if the device interrupts it when all the packets
+  are transmitted.
+
+  VIRTIO_F_RING_INDIRECT_DESC (28) Negotiating this feature
+  indicates that the driver can use descriptors with the
+  VRING_DESC_F_INDIRECT flag set, as described in [sub:Indirect-Descriptors]
+  .
+
+  VIRTIO_F_RING_EVENT_IDX(29) This feature enables the used_event
+  and the avail_event fields. If set, it indicates that the
+  device should ignore the flags field in the available ring
+  structure. Instead, the used_event field in this structure is
+  used by guest to suppress device interrupts. Further, the
+  driver should ignore the flags field in the used ring
+  structure. Instead, the avail_event field in this structure is
+  used by the device to suppress notifications. If unset, the
+  driver should ignore the used_event field; the device should
+  ignore the avail_event field; the flags field is used
+
+  VIRTIO_F_BAD_FEATURE(30) This feature should never be
+  negotiated by the guest; doing so is an indication that the
+  guest is faulty[footnote:
+An experimental virtio PCI driver contained in Linux version
+2.6.25 had this problem, and this feature bit can be used to
+detect it.
+]
+
+  VIRTIO_F_FEATURES_HIGH(31) This feature indicates that the
+  device supports feature bits 32:63. If unset, feature bits
+  32:63 are unset.
+
+Appendix C: Network Device
+
+The virtio network device is a virtual ethernet card, and is the
+most complex of the devices supported so far by virtio. It has
+enhanced rapidly and demonstrates clearly how support for new
+features should be added to an existing device. Empty buffers are
+placed in one virtqueue for receiving packets, and outgoing
+packets are enqueued into another for transmission in that order.
+A third command queue is used to control advanced filtering
+features.
+
+  Configuration
+
+  Subsystem Device ID 1
+
+  Virtqueues 0:receiveq. 1:transmitq. 2:controlq[footnote:
+Only if VIRTIO_NET_F_CTRL_VQ set
+]
+
+  Feature bits
+
+  VIRTIO_NET_F_CSUM (0) Device handles packets with partial
+    checksum
+
+  VIRTIO_NET_F_GUEST_CSUM (1) Guest handles packets with partial
+    checksum
+
+  VIRTIO_NET_F_MAC (5) Device has given MAC address.
+
+  VIRTIO_NET_F_GSO (6) (Deprecated) device handles packets with
+    any GSO type.[footnote:
+It was supposed to indicate segmentation offload support, but
+upon further investigation it became clear that multiple bits
+were required.
+]
+
+  VIRTIO_NET_F_GUEST_TSO4 (7) Guest can receive TSOv4.
+
+  VIRTIO_NET_F_GUEST_TSO6 (8) Guest can receive TSOv6.
+
+  VIRTIO_NET_F_GUEST_ECN (9) Guest can receive TSO with ECN.
+
+  VIRTIO_NET_F_GUEST_UFO (10) Guest can receive UFO.
+
+  VIRTIO_NET_F_HOST_TSO4 (11) Device can receive TSOv4.
+
+  VIRTIO_NET_F_HOST_TSO6 (12) Device can receive TSOv6.
+
+  VIRTIO_NET_F_HOST_ECN (13) Device can receive TSO with ECN.
+
+  VIRTIO_NET_F_HOST_UFO (14) Device can receive UFO.
+
+  VIRTIO_NET_F_MRG_RXBUF (15) Guest can merge receive buffers.
+
+  VIRTIO_NET_F_STATUS (16) Configuration status field is
+    available.
+
+  VIRTIO_NET_F_CTRL_VQ (17) Control channel is available.
+
+  VIRTIO_NET_F_CTRL_RX (18) Control channel RX mode support.
+
+  VIRTIO_NET_F_CTRL_VLAN (19) Control channel VLAN filtering.
+
+  Device configuration layout Two configuration fields are
+  currently defined. The mac address field always exists (though
+  is only valid if VIRTIO_NET_F_MAC is set), and the status field
+  only exists if VIRTIO_NET_F_STATUS is set. Only one bit is
+  currently defined for the status field: VIRTIO_NET_S_LINK_UP. #define VIRTIO_NET_S_LINK_UP   1
+
+
+
+struct virtio_net_config {
+
+    u8 mac[6];
+
+    u16 status;
+
+};
+
+  Device Initialization
+
+  The initialization routine should identify the receive and
+  transmission virtqueues.
+
+  If the VIRTIO_NET_F_MAC feature bit is set, the configuration
+  space “mac” entry indicates the “physical” address of the the
+  network card, otherwise a private MAC address should be
+  assigned. All guests are expected to negotiate this feature if
+  it is set.
+
+  If the VIRTIO_NET_F_CTRL_VQ feature bit is negotiated, identify
+  the control virtqueue.
+
+  If the VIRTIO_NET_F_STATUS feature bit is negotiated, the link
+  status can be read from the bottom bit of the “status” config
+  field. Otherwise, the link should be assumed active.
+
+  The receive virtqueue should be filled with receive buffers.
+  This is described in detail below in “Setting Up Receive
+  Buffers”.
+
+  A driver can indicate that it will generate checksumless
+  packets by negotating the VIRTIO_NET_F_CSUM feature. This “
+  checksum offload” is a common feature on modern network cards.
+
+  If that feature is negotiated, a driver can use TCP or UDP
+  segmentation offload by negotiating the VIRTIO_NET_F_HOST_TSO4
+  (IPv4 TCP), VIRTIO_NET_F_HOST_TSO6 (IPv6 TCP) and
+  VIRTIO_NET_F_HOST_UFO (UDP fragmentation) features. It should
+  not send TCP packets requiring segmentation offload which have
+  the Explicit Congestion Notification bit set, unless the
+  VIRTIO_NET_F_HOST_ECN feature is negotiated.[footnote:
+This is a common restriction in real, older network cards.
+]
+
+  The converse features are also available: a driver can save the
+  virtual device some work by negotiating these features.[footnote:
+For example, a network packet transported between two guests on
+the same system may not require checksumming at all, nor
+segmentation, if both guests are amenable.
+] The VIRTIO_NET_F_GUEST_CSUM feature indicates that partially
+  checksummed packets can be received, and if it can do that then
+  the VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
+  VIRTIO_NET_F_GUEST_UFO and VIRTIO_NET_F_GUEST_ECN are the input
+  equivalents of the features described above. See “Receiving
+  Packets” below.
+
+  Device Operation
+
+Packets are transmitted by placing them in the transmitq, and
+buffers for incoming packets are placed in the receiveq. In each
+case, the packet itself is preceeded by a header:
+
+struct virtio_net_hdr {
+
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM    1
+
+       u8 flags;
+
+#define VIRTIO_NET_HDR_GSO_NONE        0
+
+#define VIRTIO_NET_HDR_GSO_TCPV4       1
+
+#define VIRTIO_NET_HDR_GSO_UDP          3
+
+#define VIRTIO_NET_HDR_GSO_TCPV6       4
+
+#define VIRTIO_NET_HDR_GSO_ECN      0x80
+
+       u8 gso_type;
+
+       u16 hdr_len;
+
+       u16 gso_size;
+
+       u16 csum_start;
+
+       u16 csum_offset;
+
+/* Only if VIRTIO_NET_F_MRG_RXBUF: */
+
+       u16 num_buffers
+
+};
+
+The controlq is used to control device features such as
+filtering.
+
+  Packet Transmission
+
+Transmitting a single packet is simple, but varies depending on
+the different features the driver negotiated.
+
+  If the driver negotiated VIRTIO_NET_F_CSUM, and the packet has
+  not been fully checksummed, then the virtio_net_hdr's fields
+  are set as follows. Otherwise, the packet must be fully
+  checksummed, and flags is zero.
+
+  flags has the VIRTIO_NET_HDR_F_NEEDS_CSUM set,
+
+  <ite:csum_start-is-set>csum_start is set to the offset within
+    the packet to begin checksumming, and
+
+  csum_offset indicates how many bytes after the csum_start the
+    new (16 bit ones' complement) checksum should be placed.[footnote:
+For example, consider a partially checksummed TCP (IPv4) packet.
+It will have a 14 byte ethernet header and 20 byte IP header
+followed by the TCP header (with the TCP checksum field 16 bytes
+into that header). csum_start will be 14+20 = 34 (the TCP
+checksum includes the header), and csum_offset will be 16. The
+value in the TCP checksum field will be the sum of the TCP pseudo
+header, so that replacing it by the ones' complement checksum of
+the TCP header and body will give the correct result.
+]
+
+  <enu:If-the-driver>If the driver negotiated
+  VIRTIO_NET_F_HOST_TSO4, TSO6 or UFO, and the packet requires
+  TCP segmentation or UDP fragmentation, then the “gso_type”
+  field is set to VIRTIO_NET_HDR_GSO_TCPV4, TCPV6 or UDP.
+  (Otherwise, it is set to VIRTIO_NET_HDR_GSO_NONE). In this
+  case, packets larger than 1514 bytes can be transmitted: the
+  metadata indicates how to replicate the packet header to cut it
+  into smaller packets. The other gso fields are set:
+
+  hdr_len is a hint to the device as to how much of the header
+    needs to be kept to copy into each packet, usually set to the
+    length of the headers, including the transport header.[footnote:
+Due to various bugs in implementations, this field is not useful
+as a guarantee of the transport header size.
+]
+
+  gso_size is the size of the packet beyond that header (ie.
+    MSS).
+
+  If the driver negotiated the VIRTIO_NET_F_HOST_ECN feature, the
+    VIRTIO_NET_HDR_GSO_ECN bit may be set in “gso_type” as well,
+    indicating that the TCP packet has the ECN bit set.[footnote:
+This case is not handled by some older hardware, so is called out
+specifically in the protocol.
+]
+
+  If the driver negotiated the VIRTIO_NET_F_MRG_RXBUF feature,
+  the num_buffers field is set to zero.
+
+  The header and packet are added as one output buffer to the
+  transmitq, and the device is notified of the new entry (see [sub:Notifying-The-Device]
+  ).[footnote:
+Note that the header will be two bytes longer for the
+VIRTIO_NET_F_MRG_RXBUF case.
+]
+
+  Packet Transmission Interrupt
+
+Often a driver will suppress transmission interrupts using the
+VRING_AVAIL_F_NO_INTERRUPT flag (see [sub:Receiving-Used-Buffers]
+) and check for used packets in the transmit path of following
+packets. However, it will still receive interrupts if the
+VIRTIO_F_NOTIFY_ON_EMPTY feature is negotiated, indicating that
+the transmission queue is completely emptied.
+
+The normal behavior in this interrupt handler is to retrieve and
+new descriptors from the used ring and free the corresponding
+headers and packets.
+
+  Setting Up Receive Buffers
+
+It is generally a good idea to keep the receive virtqueue as
+fully populated as possible: if it runs out, network performance
+will suffer.
+
+If the VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6 or
+VIRTIO_NET_F_GUEST_UFO features are used, the Guest will need to
+accept packets of up to 65550 bytes long (the maximum size of a
+TCP or UDP packet, plus the 14 byte ethernet header), otherwise
+1514 bytes. So unless VIRTIO_NET_F_MRG_RXBUF is negotiated, every
+buffer in the receive queue needs to be at least this length [footnote:
+Obviously each one can be split across multiple descriptor
+elements.
+].
+
+If VIRTIO_NET_F_MRG_RXBUF is negotiated, each buffer must be at
+least the size of the struct virtio_net_hdr.
+
+  Packet Receive Interrupt
+
+When a packet is copied into a buffer in the receiveq, the
+optimal path is to disable further interrupts for the receiveq
+(see [sub:Receiving-Used-Buffers]) and process packets until no
+more are found, then re-enable them.
+
+Processing packet involves:
+
+  If the driver negotiated the VIRTIO_NET_F_MRG_RXBUF feature,
+  then the “num_buffers” field indicates how many descriptors
+  this packet is spread over (including this one). This allows
+  receipt of large packets without having to allocate large
+  buffers. In this case, there will be at least “num_buffers” in
+  the used ring, and they should be chained together to form a
+  single packet. The other buffers will not begin with a struct
+  virtio_net_hdr.
+
+  If the VIRTIO_NET_F_MRG_RXBUF feature was not negotiated, or
+  the “num_buffers” field is one, then the entire packet will be
+  contained within this buffer, immediately following the struct
+  virtio_net_hdr.
+
+  If the VIRTIO_NET_F_GUEST_CSUM feature was negotiated, the
+  VIRTIO_NET_HDR_F_NEEDS_CSUM bit in the “flags” field may be
+  set: if so, the checksum on the packet is incomplete and the “
+  csum_start” and “csum_offset” fields indicate how to calculate
+  it (see [ite:csum_start-is-set]).
+
+  If the VIRTIO_NET_F_GUEST_TSO4, TSO6 or UFO options were
+  negotiated, then the “gso_type” may be something other than
+  VIRTIO_NET_HDR_GSO_NONE, and the “gso_size” field indicates the
+  desired MSS (see [enu:If-the-driver]).Control Virtqueue
+
+The driver uses the control virtqueue (if VIRTIO_NET_F_VTRL_VQ is
+negotiated) to send commands to manipulate various features of
+the device which would not easily map into the configuration
+space.
+
+All commands are of the following form:
+
+struct virtio_net_ctrl {
+
+       u8 class;
+
+       u8 command;
+
+       u8 command-specific-data[];
+
+       u8 ack;
+
+};
+
+
+
+/* ack values */
+
+#define VIRTIO_NET_OK     0
+
+#define VIRTIO_NET_ERR    1
+
+The class, command and command-specific-data are set by the
+driver, and the device sets the ack byte. There is little it can
+do except issue a diagnostic if the ack byte is not
+VIRTIO_NET_OK.
+
+  Packet Receive Filtering
+
+If the VIRTIO_NET_F_CTRL_RX feature is negotiated, the driver can
+send control commands for promiscuous mode, multicast receiving,
+and filtering of MAC addresses.
+
+Note that in general, these commands are best-effort: unwanted
+packets may still arrive.
+
+  Setting Promiscuous Mode
+
+#define VIRTIO_NET_CTRL_RX    0
+
+ #define VIRTIO_NET_CTRL_RX_PROMISC      0
+
+ #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
+
+The class VIRTIO_NET_CTRL_RX has two commands:
+VIRTIO_NET_CTRL_RX_PROMISC turns promiscuous mode on and off, and
+VIRTIO_NET_CTRL_RX_ALLMULTI turns all-multicast receive on and
+off. The command-specific-data is one byte containing 0 (off) or
+1 (on).
+
+  Setting MAC Address Filtering
+
+struct virtio_net_ctrl_mac {
+
+       u32 entries;
+
+       u8 macs[entries][ETH_ALEN];
+
+};
+
+
+
+#define VIRTIO_NET_CTRL_MAC    1
+
+ #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
+
+The device can filter incoming packets by any number of
+destination MAC addresses.[footnote:
+Since there are no guarentees, it can use a hash filter
+orsilently switch to allmulti or promiscuous mode if it is given
+too many addresses.
+] This table is set using the class VIRTIO_NET_CTRL_MAC and the
+command VIRTIO_NET_CTRL_MAC_TABLE_SET. The command-specific-data
+is two variable length tables of 6-byte MAC addresses. The first
+table contains unicast addresses, and the second contains
+multicast addresses.
+
+  VLAN Filtering
+
+If the driver negotiates the VIRTION_NET_F_CTRL_VLAN feature, it
+can control a VLAN filter table in the device.
+
+#define VIRTIO_NET_CTRL_VLAN       2
+
+ #define VIRTIO_NET_CTRL_VLAN_ADD             0
+
+ #define VIRTIO_NET_CTRL_VLAN_DEL             1
+
+Both the VIRTIO_NET_CTRL_VLAN_ADD and VIRTIO_NET_CTRL_VLAN_DEL
+command take a 16-bit VLAN id as the command-specific-data.
+
+Appendix D: Block Device
+
+The virtio block device is a simple virtual block device (ie.
+disk). Read and write requests (and other exotic requests) are
+placed in the queue, and serviced (probably out of order) by the
+device except where noted.
+
+  Configuration
+
+  Subsystem Device ID 2
+
+  Virtqueues 0:requestq.
+
+  Feature bits
+
+  VIRTIO_BLK_F_BARRIER (0) Host supports request barriers.
+
+  VIRTIO_BLK_F_SIZE_MAX (1) Maximum size of any single segment is
+    in “size_max”.
+
+  VIRTIO_BLK_F_SEG_MAX (2) Maximum number of segments in a
+    request is in “seg_max”.
+
+  VIRTIO_BLK_F_GEOMETRY (4) Disk-style geometry specified in “
+    geometry”.
+
+  VIRTIO_BLK_F_RO (5) Device is read-only.
+
+  VIRTIO_BLK_F_BLK_SIZE (6) Block size of disk is in “blk_size”.
+
+  VIRTIO_BLK_F_SCSI (7) Device supports scsi packet commands.
+
+  VIRTIO_BLK_F_FLUSH (9) Cache flush command support.
+
+
+
+  Device configuration layout The capacity of the device
+  (expressed in 512-byte sectors) is always present. The
+  availability of the others all depend on various feature bits
+  as indicated above. struct virtio_blk_config {
+
+       u64 capacity;
+
+       u32 size_max;
+
+       u32 seg_max;
+
+       struct virtio_blk_geometry {
+
+               u16 cylinders;
+
+               u8 heads;
+
+               u8 sectors;
+
+       } geometry;
+
+       u32 blk_size;
+
+
+
+};
+
+  Device Initialization
+
+  The device size should be read from the “capacity”
+  configuration field. No requests should be submitted which goes
+  beyond this limit.
+
+  If the VIRTIO_BLK_F_BLK_SIZE feature is negotiated, the
+  blk_size field can be read to determine the optimal sector size
+  for the driver to use. This does not effect the units used in
+  the protocol (always 512 bytes), but awareness of the correct
+  value can effect performance.
+
+  If the VIRTIO_BLK_F_RO feature is set by the device, any write
+  requests will fail.
+
+
+
+  Device Operation
+
+The driver queues requests to the virtqueue, and they are used by
+the device (not necessarily in order). Each request is of form:
+
+struct virtio_blk_req {
+
+
+
+       u32 type;
+
+       u32 ioprio;
+
+       u64 sector;
+
+       char data[][512];
+
+       u8 status;
+
+};
+
+If the device has VIRTIO_BLK_F_SCSI feature, it can also support
+scsi packet command requests, each of these requests is of form:struct virtio_scsi_pc_req {
+
+       u32 type;
+
+       u32 ioprio;
+
+       u64 sector;
+
+    char cmd[];
+
+       char data[][512];
+
+#define SCSI_SENSE_BUFFERSIZE   96
+
+    u8 sense[SCSI_SENSE_BUFFERSIZE];
+
+    u32 errors;
+
+    u32 data_len;
+
+    u32 sense_len;
+
+    u32 residual;
+
+       u8 status;
+
+};
+
+The type of the request is either a read (VIRTIO_BLK_T_IN), a
+write (VIRTIO_BLK_T_OUT), a scsi packet command
+(VIRTIO_BLK_T_SCSI_CMD or VIRTIO_BLK_T_SCSI_CMD_OUT[footnote:
+the SCSI_CMD and SCSI_CMD_OUT types are equivalent, the device
+does not distinguish between them
+]) or a flush (VIRTIO_BLK_T_FLUSH or VIRTIO_BLK_T_FLUSH_OUT[footnote:
+the FLUSH and FLUSH_OUT types are equivalent, the device does not
+distinguish between them
+]). If the device has VIRTIO_BLK_F_BARRIER feature the high bit
+(VIRTIO_BLK_T_BARRIER) indicates that this request acts as a
+barrier and that all preceeding requests must be complete before
+this one, and all following requests must not be started until
+this is complete. Note that a barrier does not flush caches in
+the underlying backend device in host, and thus does not serve as
+data consistency guarantee. Driver must use FLUSH request to
+flush the host cache.
+
+#define VIRTIO_BLK_T_IN           0
+
+#define VIRTIO_BLK_T_OUT          1
+
+#define VIRTIO_BLK_T_SCSI_CMD     2
+
+#define VIRTIO_BLK_T_SCSI_CMD_OUT 3
+
+#define VIRTIO_BLK_T_FLUSH        4
+
+#define VIRTIO_BLK_T_FLUSH_OUT    5
+
+#define VIRTIO_BLK_T_BARRIER    0x80000000
+
+The ioprio field is a hint about the relative priorities of
+requests to the device: higher numbers indicate more important
+requests.
+
+The sector number indicates the offset (multiplied by 512) where
+the read or write is to occur. This field is unused and set to 0
+for scsi packet commands and for flush commands.
+
+The cmd field is only present for scsi packet command requests,
+and indicates the command to perform. This field must reside in a
+single, separate read-only buffer; command length can be derived
+from the length of this buffer.
+
+Note that these first three (four for scsi packet commands)
+fields are always read-only: the data field is either read-only
+or write-only, depending on the request. The size of the read or
+write can be derived from the total size of the request buffers.
+
+The sense field is only present for scsi packet command requests,
+and indicates the buffer for scsi sense data.
+
+The data_len field is only present for scsi packet command
+requests, this field is deprecated, and should be ignored by the
+driver. Historically, devices copied data length there.
+
+The sense_len field is only present for scsi packet command
+requests and indicates the number of bytes actually written to
+the sense buffer.
+
+The residual field is only present for scsi packet command
+requests and indicates the residual size, calculated as data
+length - number of bytes actually transferred.
+
+The final status byte is written by the device: either
+VIRTIO_BLK_S_OK for success, VIRTIO_BLK_S_IOERR for host or guest
+error or VIRTIO_BLK_S_UNSUPP for a request unsupported by host:#define VIRTIO_BLK_S_OK        0
+
+#define VIRTIO_BLK_S_IOERR     1
+
+#define VIRTIO_BLK_S_UNSUPP    2
+
+Historically, devices assumed that the fields type, ioprio and
+sector reside in a single, separate read-only buffer; the fields
+errors, data_len, sense_len and residual reside in a single,
+separate write-only buffer; the sense field in a separate
+write-only buffer of size 96 bytes, by itself; the fields errors,
+data_len, sense_len and residual in a single write-only buffer;
+and the status field is a separate read-only buffer of size 1
+byte, by itself.
+
+Appendix E: Console Device
+
+The virtio console device is a simple device for data input and
+output. A device may have one or more ports. Each port has a pair
+of input and output virtqueues. Moreover, a device has a pair of
+control IO virtqueues. The control virtqueues are used to
+communicate information between the device and the driver about
+ports being opened and closed on either side of the connection,
+indication from the host about whether a particular port is a
+console port, adding new ports, port hot-plug/unplug, etc., and
+indication from the guest about whether a port or a device was
+successfully added, port open/close, etc.. For data IO, one or
+more empty buffers are placed in the receive queue for incoming
+data and outgoing characters are placed in the transmit queue.
+
+  Configuration
+
+  Subsystem Device ID 3
+
+  Virtqueues 0:receiveq(port0). 1:transmitq(port0), 2:control
+  receiveq[footnote:
+Ports 2 onwards only if VIRTIO_CONSOLE_F_MULTIPORT is set
+], 3:control transmitq, 4:receiveq(port1), 5:transmitq(port1),
+  ...
+
+  Feature bits
+
+  VIRTIO_CONSOLE_F_SIZE (0) Configuration cols and rows fields
+    are valid.
+
+  VIRTIO_CONSOLE_F_MULTIPORT(1) Device has support for multiple
+    ports; configuration fields nr_ports and max_nr_ports are
+    valid and control virtqueues will be used.
+
+  Device configuration layout The size of the console is supplied
+  in the configuration space if the VIRTIO_CONSOLE_F_SIZE feature
+  is set. Furthermore, if the VIRTIO_CONSOLE_F_MULTIPORT feature
+  is set, the maximum number of ports supported by the device can
+  be fetched.struct virtio_console_config {
+
+       u16 cols;
+
+       u16 rows;
+
+
+
+       u32 max_nr_ports;
+
+};
+
+  Device Initialization
+
+  If the VIRTIO_CONSOLE_F_SIZE feature is negotiated, the driver
+  can read the console dimensions from the configuration fields.
+
+  If the VIRTIO_CONSOLE_F_MULTIPORT feature is negotiated, the
+  driver can spawn multiple ports, not all of which may be
+  attached to a console. Some could be generic ports. In this
+  case, the control virtqueues are enabled and according to the
+  max_nr_ports configuration-space value, the appropriate number
+  of virtqueues are created. A control message indicating the
+  driver is ready is sent to the host. The host can then send
+  control messages for adding new ports to the device. After
+  creating and initializing each port, a
+  VIRTIO_CONSOLE_PORT_READY control message is sent to the host
+  for that port so the host can let us know of any additional
+  configuration options set for that port.
+
+  The receiveq for each port is populated with one or more
+  receive buffers.
+
+  Device Operation
+
+  For output, a buffer containing the characters is placed in the
+  port's transmitq.[footnote:
+Because this is high importance and low bandwidth, the current
+Linux implementation polls for the buffer to be used, rather than
+waiting for an interrupt, simplifying the implementation
+significantly. However, for generic serial ports with the
+O_NONBLOCK flag set, the polling limitation is relaxed and the
+consumed buffers are freed upon the next write or poll call or
+when a port is closed or hot-unplugged.
+]
+
+  When a buffer is used in the receiveq (signalled by an
+  interrupt), the contents is the input to the port associated
+  with the virtqueue for which the notification was received.
+
+  If the driver negotiated the VIRTIO_CONSOLE_F_SIZE feature, a
+  configuration change interrupt may occur. The updated size can
+  be read from the configuration fields.
+
+  If the driver negotiated the VIRTIO_CONSOLE_F_MULTIPORT
+  feature, active ports are announced by the host using the
+  VIRTIO_CONSOLE_PORT_ADD control message. The same message is
+  used for port hot-plug as well.
+
+  If the host specified a port `name', a sysfs attribute is
+  created with the name filled in, so that udev rules can be
+  written that can create a symlink from the port's name to the
+  char device for port discovery by applications in the guest.
+
+  Changes to ports' state are effected by control messages.
+  Appropriate action is taken on the port indicated in the
+  control message. The layout of the structure of the control
+  buffer and the events associated are:struct virtio_console_control {
+
+       uint32_t id;    /* Port number */
+
+       uint16_t event; /* The kind of control event */
+
+       uint16_t value; /* Extra information for the event */
+
+};
+
+
+
+/* Some events for the internal messages (control packets) */
+
+
+
+#define VIRTIO_CONSOLE_DEVICE_READY     0
+
+#define VIRTIO_CONSOLE_PORT_ADD         1
+
+#define VIRTIO_CONSOLE_PORT_REMOVE      2
+
+#define VIRTIO_CONSOLE_PORT_READY       3
+
+#define VIRTIO_CONSOLE_CONSOLE_PORT     4
+
+#define VIRTIO_CONSOLE_RESIZE           5
+
+#define VIRTIO_CONSOLE_PORT_OPEN        6
+
+#define VIRTIO_CONSOLE_PORT_NAME        7
+
+Appendix F: Entropy Device
+
+The virtio entropy device supplies high-quality randomness for
+guest use.
+
+  Configuration
+
+  Subsystem Device ID 4
+
+  Virtqueues 0:requestq.
+
+  Feature bits None currently defined
+
+  Device configuration layout None currently defined.
+
+  Device Initialization
+
+  The virtqueue is initialized
+
+  Device Operation
+
+When the driver requires random bytes, it places the descriptor
+of one or more buffers in the queue. It will be completely filled
+by random data by the device.
+
+Appendix G: Memory Balloon Device
+
+The virtio memory balloon device is a primitive device for
+managing guest memory: the device asks for a certain amount of
+memory, and the guest supplies it (or withdraws it, if the device
+has more than it asks for). This allows the guest to adapt to
+changes in allowance of underlying physical memory. If the
+feature is negotiated, the device can also be used to communicate
+guest memory statistics to the host.
+
+  Configuration
+
+  Subsystem Device ID 5
+
+  Virtqueues 0:inflateq. 1:deflateq. 2:statsq.[footnote:
+Only if VIRTIO_BALLON_F_STATS_VQ set
+]
+
+  Feature bits
+
+  VIRTIO_BALLOON_F_MUST_TELL_HOST (0) Host must be told before
+    pages from the balloon are used.
+
+  VIRTIO_BALLOON_F_STATS_VQ (1) A virtqueue for reporting guest
+    memory statistics is present.
+
+  Device configuration layout Both fields of this configuration
+  are always available. Note that they are little endian, despite
+  convention that device fields are guest endian:struct virtio_balloon_config {
+
+       u32 num_pages;
+
+       u32 actual;
+
+};
+
+  Device Initialization
+
+  The inflate and deflate virtqueues are identified.
+
+  If the VIRTIO_BALLOON_F_STATS_VQ feature bit is negotiated:
+
+  Identify the stats virtqueue.
+
+  Add one empty buffer to the stats virtqueue and notify the
+    host.
+
+Device operation begins immediately.
+
+  Device Operation
+
+  Memory Ballooning The device is driven by the receipt of a
+  configuration change interrupt.
+
+  The “num_pages” configuration field is examined. If this is
+  greater than the “actual” number of pages, memory must be given
+  to the balloon. If it is less than the “actual” number of
+  pages, memory may be taken back from the balloon for general
+  use.
+
+  To supply memory to the balloon (aka. inflate):
+
+  The driver constructs an array of addresses of unused memory
+    pages. These addresses are divided by 4096[footnote:
+This is historical, and independent of the guest page size
+] and the descriptor describing the resulting 32-bit array is
+    added to the inflateq.
+
+  To remove memory from the balloon (aka. deflate):
+
+  The driver constructs an array of addresses of memory pages it
+    has previously given to the balloon, as described above. This
+    descriptor is added to the deflateq.
+
+  If the VIRTIO_BALLOON_F_MUST_TELL_HOST feature is set, the
+    guest may not use these requested pages until that descriptor
+    in the deflateq has been used by the device.
+
+  Otherwise, the guest may begin to re-use pages previously given
+    to the balloon before the device has acknowledged their
+    withdrawl. [footnote:
+In this case, deflation advice is merely a courtesy
+]
+
+  In either case, once the device has completed the inflation or
+  deflation, the “actual” field of the configuration should be
+  updated to reflect the new number of pages in the balloon.[footnote:
+As updates to configuration space are not atomic, this field
+isn't particularly reliable, but can be used to diagnose buggy
+guests.
+]
+
+  Memory Statistics
+
+The stats virtqueue is atypical because communication is driven
+by the device (not the driver). The channel becomes active at
+driver initialization time when the driver adds an empty buffer
+and notifies the device. A request for memory statistics proceeds
+as follows:
+
+  The device pushes the buffer onto the used ring and sends an
+  interrupt.
+
+  The driver pops the used buffer and discards it.
+
+  The driver collects memory statistics and writes them into a
+  new buffer.
+
+  The driver adds the buffer to the virtqueue and notifies the
+  device.
+
+  The device pops the buffer (retaining it to initiate a
+  subsequent request) and consumes the statistics.
+
+  Memory Statistics Format Each statistic consists of a 16 bit
+  tag and a 64 bit value. Both quantities are represented in the
+  native endian of the guest. All statistics are optional and the
+  driver may choose which ones to supply. To guarantee backwards
+  compatibility, unsupported statistics should be omitted.
+
+  struct virtio_balloon_stat {
+
+#define VIRTIO_BALLOON_S_SWAP_IN  0
+
+#define VIRTIO_BALLOON_S_SWAP_OUT 1
+
+#define VIRTIO_BALLOON_S_MAJFLT   2
+
+#define VIRTIO_BALLOON_S_MINFLT   3
+
+#define VIRTIO_BALLOON_S_MEMFREE  4
+
+#define VIRTIO_BALLOON_S_MEMTOT   5
+
+       u16 tag;
+
+       u64 val;
+
+} __attribute__((packed));
+
+  Tags
+
+  VIRTIO_BALLOON_S_SWAP_IN The amount of memory that has been
+  swapped in (in bytes).
+
+  VIRTIO_BALLOON_S_SWAP_OUT The amount of memory that has been
+  swapped out to disk (in bytes).
+
+  VIRTIO_BALLOON_S_MAJFLT The number of major page faults that
+  have occurred.
+
+  VIRTIO_BALLOON_S_MINFLT The number of minor page faults that
+  have occurred.
+
+  VIRTIO_BALLOON_S_MEMFREE The amount of memory not being used
+  for any purpose (in bytes).
+
+  VIRTIO_BALLOON_S_MEMTOT The total amount of memory available
+  (in bytes).
+
index 1e55e1e..28f65c2 100644 (file)
@@ -1883,7 +1883,7 @@ S:        Maintained
 F:     drivers/connector/
 
 CONTROL GROUPS (CGROUPS)
-M:     Paul Menage <menage@google.com>
+M:     Paul Menage <paul@paulmenage.org>
 M:     Li Zefan <lizf@cn.fujitsu.com>
 L:     containers@lists.linux-foundation.org
 S:     Maintained
@@ -1932,7 +1932,7 @@ S:        Maintained
 F:     tools/power/cpupower
 
 CPUSETS
-M:     Paul Menage <menage@google.com>
+M:     Paul Menage <paul@paulmenage.org>
 W:     http://www.bullopensource.org/cpuset/
 W:     http://oss.sgi.com/projects/cpusets/
 S:     Supported
@@ -2649,11 +2649,11 @@ F:      drivers/net/wan/dlci.c
 F:     drivers/net/wan/sdla.c
 
 FRAMEBUFFER LAYER
-M:     Paul Mundt <lethal@linux-sh.org>
+M:     Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
 L:     linux-fbdev@vger.kernel.org
 W:     http://linux-fbdev.sourceforge.net/
 Q:     http://patchwork.kernel.org/project/linux-fbdev/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6.git
+T:     git git://github.com/schandinat/linux-2.6.git fbdev-next
 S:     Maintained
 F:     Documentation/fb/
 F:     Documentation/devicetree/bindings/fb/
@@ -4450,8 +4450,8 @@ M:        "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
 W:     http://patchwork.ozlabs.org/project/netdev/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:     Maintained
 F:     net/
 F:     include/net/
@@ -4604,7 +4604,7 @@ F:        arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
 F:     arch/arm/mach-omap2/clockdomain44xx.c
 
 OMAP AUDIO SUPPORT
-M:     Jarkko Nikula <jhnikula@gmail.com>
+M:     Jarkko Nikula <jarkko.nikula@bitmer.com>
 L:     alsa-devel@alsa-project.org (subscribers-only)
 L:     linux-omap@vger.kernel.org
 S:     Maintained
@@ -4971,7 +4971,7 @@ M:        Paul Mackerras <paulus@samba.org>
 M:     Ingo Molnar <mingo@elte.hu>
 M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 S:     Supported
-F:     kernel/perf_event*.c
+F:     kernel/events/*
 F:     include/linux/perf_event.h
 F:     arch/*/kernel/perf_event*.c
 F:     arch/*/kernel/*/perf_event*.c
@@ -5532,6 +5532,7 @@ F:        include/media/*7146*
 
 SAMSUNG AUDIO (ASoC) DRIVERS
 M:     Jassi Brar <jassisinghbrar@gmail.com>
+M:     Sangbeom Kim <sbkim73@samsung.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     sound/soc/samsung
@@ -7087,7 +7088,7 @@ S:        Supported
 F:     drivers/mmc/host/vub300.c
 
 W1 DALLAS'S 1-WIRE BUS
-M:     Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+M:     Evgeniy Polyakov <zbr@ioremap.net>
 S:     Maintained
 F:     Documentation/w1/
 F:     drivers/w1/
index b4ca4e1..522fa47 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 1
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
-NAME = Sneaky Weasel
+EXTRAVERSION = -rc6
+NAME = "Divemaster Edition"
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 086aba2..e77d77c 100644 (file)
 #define UAC_NOFIX                      2
 #define UAC_SIGBUS                     4
 
-
-#ifdef __KERNEL__
-
-/* This is the shift that is applied to the UAC bits as stored in the
-   per-thread flags.  See thread_info.h.  */
-#define UAC_SHIFT                      6
-
-#endif
-
 #endif /* __ASM_ALPHA_SYSINFO_H */
index 6f32f9c..ff73db0 100644 (file)
@@ -74,9 +74,9 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_POLLING_NRFLAG     8       /* poll_idle is polling NEED_RESCHED */
 #define TIF_DIE_IF_KERNEL      9       /* dik recursion lock */
-#define TIF_UAC_NOPRINT                10      /* see sysinfo.h */
-#define TIF_UAC_NOFIX          11
-#define TIF_UAC_SIGBUS         12
+#define TIF_UAC_NOPRINT                10      /* ! Preserve sequence of following */
+#define TIF_UAC_NOFIX          11      /* ! flags as they match            */
+#define TIF_UAC_SIGBUS         12      /* ! userspace part of 'osf_sysinfo' */
 #define TIF_MEMDIE             13      /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    14      /* restore signal mask in do_signal */
 #define TIF_FREEZE             16      /* is freezing for suspend */
@@ -97,7 +97,7 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK         \
                                 | _TIF_SYSCALL_TRACE)
 
-#define ALPHA_UAC_SHIFT                10
+#define ALPHA_UAC_SHIFT                TIF_UAC_NOPRINT
 #define ALPHA_UAC_MASK         (1 << TIF_UAC_NOPRINT | 1 << TIF_UAC_NOFIX | \
                                 1 << TIF_UAC_SIGBUS)
 
index 326f0a2..01e8715 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/sysinfo.h>
+#include <asm/thread_info.h>
 #include <asm/hwrpb.h>
 #include <asm/processor.h>
 
@@ -633,9 +634,10 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
        case GSI_UACPROC:
                if (nbytes < sizeof(unsigned int))
                        return -EINVAL;
-               w = (current_thread_info()->flags >> UAC_SHIFT) & UAC_BITMASK;
-               if (put_user(w, (unsigned int __user *)buffer))
-                       return -EFAULT;
+               w = (current_thread_info()->flags >> ALPHA_UAC_SHIFT) &
+                       UAC_BITMASK;
+               if (put_user(w, (unsigned int __user *)buffer))
+                       return -EFAULT;
                return 1;
 
        case GSI_PROC_TYPE:
@@ -756,8 +758,8 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
                        case SSIN_UACPROC:
                        again:
                                old = current_thread_info()->flags;
-                               new = old & ~(UAC_BITMASK << UAC_SHIFT);
-                               new = new | (w & UAC_BITMASK) << UAC_SHIFT;
+                               new = old & ~(UAC_BITMASK << ALPHA_UAC_SHIFT);
+                               new = new | (w & UAC_BITMASK) << ALPHA_UAC_SHIFT;
                                if (cmpxchg(&current_thread_info()->flags,
                                            old, new) != old)
                                        goto again;
index b9c28f3..6acea1f 100644 (file)
@@ -360,7 +360,7 @@ sys_call_table:
        .quad sys_newuname
        .quad sys_nanosleep                     /* 340 */
        .quad sys_mremap
-       .quad sys_nfsservctl
+       .quad sys_ni_syscall                    /* old nfsservctl */
        .quad sys_setresuid
        .quad sys_getresuid
        .quad sys_pciconfig_read                /* 345 */
index 3269576..5a3a786 100644 (file)
@@ -1793,6 +1793,38 @@ config ZBOOT_ROM_SH_MOBILE_SDHI
 
 endchoice
 
+config ARM_APPENDED_DTB
+       bool "Use appended device tree blob to zImage (EXPERIMENTAL)"
+       depends on OF && !ZBOOT_ROM && EXPERIMENTAL
+       help
+         With this option, the boot code will look for a device tree binary
+         (DTB) appended to zImage
+         (e.g. cat zImage <filename>.dtb > zImage_w_dtb).
+
+         This is meant as a backward compatibility convenience for those
+         systems with a bootloader that can't be upgraded to accommodate
+         the documented boot protocol using a device tree.
+
+         Beware that there is very little in terms of protection against
+         this option being confused by leftover garbage in memory that might
+         look like a DTB header after a reboot if no actual DTB is appended
+         to zImage.  Do not leave this option active in a production kernel
+         if you don't intend to always append a DTB.  Proper passing of the
+         location into r2 of a bootloader provided DTB is always preferable
+         to this option.
+
+config ARM_ATAG_DTB_COMPAT
+       bool "Supplement the appended DTB with traditional ATAG information"
+       depends on ARM_APPENDED_DTB
+       help
+         Some old bootloaders can't be updated to a DTB capable one, yet
+         they provide ATAGs with memory configuration, the ramdisk address,
+         the kernel cmdline string, etc.  Such information is dynamically
+         provided by the bootloader and can't always be stored in a static
+         DTB.  To allow a device tree enabled kernel to be used with such
+         bootloaders, this option allows zImage to extract the information
+         from the ATAG list and store it at run time into the appended DTB.
+
 config CMDLINE
        string "Default kernel command string"
        default ""
index 81cbe40..be3a0f7 100644 (file)
@@ -129,4 +129,10 @@ config DEBUG_S3C_UART
          The uncompressor code port configuration is now handled
          by CONFIG_S3C_LOWLEVEL_UART_PORT.
 
+config ARM_KPROBES_TEST
+       tristate "Kprobes test module"
+       depends on KPROBES && MODULES
+       help
+         Perform tests of kprobes API and instruction set simulation.
+
 endmenu
index c602896..e0936a1 100644 (file)
@@ -5,3 +5,12 @@ piggy.lzo
 piggy.lzma
 vmlinux
 vmlinux.lds
+
+# borrowed libfdt files
+fdt.c
+fdt.h
+fdt_ro.c
+fdt_rw.c
+fdt_wip.c
+libfdt.h
+libfdt_internal.h
index 0c74a6f..e4f32a8 100644 (file)
@@ -26,6 +26,10 @@ HEAD = head.o
 OBJS   += misc.o decompress.o
 FONTC  = $(srctree)/drivers/video/console/font_acorn_8x8.c
 
+# string library code (-Os is enforced to keep it much smaller)
+OBJS           += string.o
+CFLAGS_string.o        := -Os
+
 #
 # Architecture dependencies
 #
@@ -89,21 +93,41 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip
 suffix_$(CONFIG_KERNEL_LZO)  = lzo
 suffix_$(CONFIG_KERNEL_LZMA) = lzma
 
+# Borrowed libfdt files for the ATAG compatibility mode
+
+libfdt         := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c
+libfdt_hdrs    := fdt.h libfdt.h libfdt_internal.h
+
+libfdt_objs    := $(addsuffix .o, $(basename $(libfdt)))
+
+$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
+       $(call cmd,shipped)
+
+$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
+       $(addprefix $(obj)/,$(libfdt_hdrs))
+
+ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
+OBJS   += $(libfdt_objs) atags_to_fdt.o
+endif
+
 targets       := vmlinux vmlinux.lds \
                 piggy.$(suffix_y) piggy.$(suffix_y).o \
-                font.o font.c head.o misc.o $(OBJS)
+                lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
 
 # Make sure files are removed during clean
-extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
+extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
-ccflags-y := -fpic -fno-builtin
+ccflags-y := -fpic -fno-builtin -I$(obj)
 asflags-y := -Wa,-march=all
 
+# Supply kernel BSS size to the decompressor via a linker symbol.
+KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}')
+LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
 # Supply ZRELADDR to the decompressor via a linker symbol.
 ifneq ($(CONFIG_AUTO_ZRELADDR),y)
 LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
@@ -123,7 +147,7 @@ LDFLAGS_vmlinux += -T
 # For __aeabi_uidivmod
 lib1funcs = $(obj)/lib1funcs.o
 
-$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
+$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
        $(call cmd,shipped)
 
 # We need to prevent any GOTOFF relocs being used with references
diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c
new file mode 100644 (file)
index 0000000..6ce11c4
--- /dev/null
@@ -0,0 +1,97 @@
+#include <asm/setup.h>
+#include <libfdt.h>
+
+static int node_offset(void *fdt, const char *node_path)
+{
+       int offset = fdt_path_offset(fdt, node_path);
+       if (offset == -FDT_ERR_NOTFOUND)
+               offset = fdt_add_subnode(fdt, 0, node_path);
+       return offset;
+}
+
+static int setprop(void *fdt, const char *node_path, const char *property,
+                  uint32_t *val_array, int size)
+{
+       int offset = node_offset(fdt, node_path);
+       if (offset < 0)
+               return offset;
+       return fdt_setprop(fdt, offset, property, val_array, size);
+}
+
+static int setprop_string(void *fdt, const char *node_path,
+                         const char *property, const char *string)
+{
+       int offset = node_offset(fdt, node_path);
+       if (offset < 0)
+               return offset;
+       return fdt_setprop_string(fdt, offset, property, string);
+}
+
+static int setprop_cell(void *fdt, const char *node_path,
+                       const char *property, uint32_t val)
+{
+       int offset = node_offset(fdt, node_path);
+       if (offset < 0)
+               return offset;
+       return fdt_setprop_cell(fdt, offset, property, val);
+}
+
+/*
+ * Convert and fold provided ATAGs into the provided FDT.
+ *
+ * REturn values:
+ *    = 0 -> pretend success
+ *    = 1 -> bad ATAG (may retry with another possible ATAG pointer)
+ *    < 0 -> error from libfdt
+ */
+int atags_to_fdt(void *atag_list, void *fdt, int total_space)
+{
+       struct tag *atag = atag_list;
+       uint32_t mem_reg_property[2 * NR_BANKS];
+       int memcount = 0;
+       int ret;
+
+       /* make sure we've got an aligned pointer */
+       if ((u32)atag_list & 0x3)
+               return 1;
+
+       /* if we get a DTB here we're done already */
+       if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
+              return 0;
+
+       /* validate the ATAG */
+       if (atag->hdr.tag != ATAG_CORE ||
+           (atag->hdr.size != tag_size(tag_core) &&
+            atag->hdr.size != 2))
+               return 1;
+
+       /* let's give it all the room it could need */
+       ret = fdt_open_into(fdt, fdt, total_space);
+       if (ret < 0)
+               return ret;
+
+       for_each_tag(atag, atag_list) {
+               if (atag->hdr.tag == ATAG_CMDLINE) {
+                       setprop_string(fdt, "/chosen", "bootargs",
+                                       atag->u.cmdline.cmdline);
+               } else if (atag->hdr.tag == ATAG_MEM) {
+                       if (memcount >= sizeof(mem_reg_property)/4)
+                               continue;
+                       mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
+                       mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
+               } else if (atag->hdr.tag == ATAG_INITRD2) {
+                       uint32_t initrd_start, initrd_size;
+                       initrd_start = atag->u.initrd.start;
+                       initrd_size = atag->u.initrd.size;
+                       setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                       initrd_start);
+                       setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                                       initrd_start + initrd_size);
+               }
+       }
+
+       if (memcount)
+               setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
+
+       return fdt_pack(fdt);
+}
index e95a598..9f5ac11 100644 (file)
@@ -216,6 +216,103 @@ restart:  adr     r0, LC0
                mov     r10, r6
 #endif
 
+               mov     r5, #0                  @ init dtb size to 0
+#ifdef CONFIG_ARM_APPENDED_DTB
+/*
+ *   r0  = delta
+ *   r2  = BSS start
+ *   r3  = BSS end
+ *   r4  = final kernel address
+ *   r5  = appended dtb size (still unknown)
+ *   r6  = _edata
+ *   r7  = architecture ID
+ *   r8  = atags/device tree pointer
+ *   r9  = size of decompressed image
+ *   r10 = end of this image, including  bss/stack/malloc space if non XIP
+ *   r11 = GOT start
+ *   r12 = GOT end
+ *   sp  = stack pointer
+ *
+ * if there are device trees (dtb) appended to zImage, advance r10 so that the
+ * dtb data will get relocated along with the kernel if necessary.
+ */
+
+               ldr     lr, [r6, #0]
+#ifndef __ARMEB__
+               ldr     r1, =0xedfe0dd0         @ sig is 0xd00dfeed big endian
+#else
+               ldr     r1, =0xd00dfeed
+#endif
+               cmp     lr, r1
+               bne     dtb_check_done          @ not found
+
+#ifdef CONFIG_ARM_ATAG_DTB_COMPAT
+               /*
+                * OK... Let's do some funky business here.
+                * If we do have a DTB appended to zImage, and we do have
+                * an ATAG list around, we want the later to be translated
+                * and folded into the former here.  To be on the safe side,
+                * let's temporarily move  the stack away into the malloc
+                * area.  No GOT fixup has occurred yet, but none of the
+                * code we're about to call uses any global variable.
+               */
+               add     sp, sp, #0x10000
+               stmfd   sp!, {r0-r3, ip, lr}
+               mov     r0, r8
+               mov     r1, r6
+               sub     r2, sp, r6
+               bl      atags_to_fdt
+
+               /*
+                * If returned value is 1, there is no ATAG at the location
+                * pointed by r8.  Try the typical 0x100 offset from start
+                * of RAM and hope for the best.
+                */
+               cmp     r0, #1
+               sub     r0, r4, #(TEXT_OFFSET - 0x100)
+               mov     r1, r6
+               sub     r2, sp, r6
+               blne    atags_to_fdt
+
+               ldmfd   sp!, {r0-r3, ip, lr}
+               sub     sp, sp, #0x10000
+#endif
+
+               mov     r8, r6                  @ use the appended device tree
+
+               /*
+                * Make sure that the DTB doesn't end up in the final
+                * kernel's .bss area. To do so, we adjust the decompressed
+                * kernel size to compensate if that .bss size is larger
+                * than the relocated code.
+                */
+               ldr     r5, =_kernel_bss_size
+               adr     r1, wont_overwrite
+               sub     r1, r6, r1
+               subs    r1, r5, r1
+               addhi   r9, r9, r1
+
+               /* Get the dtb's size */
+               ldr     r5, [r6, #4]
+#ifndef __ARMEB__
+               /* convert r5 (dtb size) to little endian */
+               eor     r1, r5, r5, ror #16
+               bic     r1, r1, #0x00ff0000
+               mov     r5, r5, ror #8
+               eor     r5, r5, r1, lsr #8
+#endif
+
+               /* preserve 64-bit alignment */
+               add     r5, r5, #7
+               bic     r5, r5, #7
+
+               /* relocate some pointers past the appended dtb */
+               add     r6, r6, r5
+               add     r10, r10, r5
+               add     sp, sp, r5
+dtb_check_done:
+#endif
+
 /*
  * Check to see if we will overwrite ourselves.
  *   r4  = final kernel address
@@ -223,15 +320,14 @@ restart:  adr     r0, LC0
  *   r10 = end of this image, including  bss/stack/malloc space if non XIP
  * We basically want:
  *   r4 - 16k page directory >= r10 -> OK
- *   r4 + image length <= current position (pc) -> OK
+ *   r4 + image length <= address of wont_overwrite -> OK
  */
                add     r10, r10, #16384
                cmp     r4, r10
                bhs     wont_overwrite
                add     r10, r4, r9
-   ARM(                cmp     r10, pc         )
- THUMB(                mov     lr, pc          )
- THUMB(                cmp     r10, lr         )
+               adr     r9, wont_overwrite
+               cmp     r10, r9
                bls     wont_overwrite
 
 /*
@@ -285,14 +381,16 @@ wont_overwrite:
  *   r2  = BSS start
  *   r3  = BSS end
  *   r4  = kernel execution address
+ *   r5  = appended dtb size (0 if not present)
  *   r7  = architecture ID
  *   r8  = atags pointer
  *   r11 = GOT start
  *   r12 = GOT end
  *   sp  = stack pointer
  */
-               teq     r0, #0
+               orrs    r1, r0, r5
                beq     not_relocated
+
                add     r11, r11, r0
                add     r12, r12, r0
 
@@ -307,12 +405,21 @@ wont_overwrite:
 
                /*
                 * Relocate all entries in the GOT table.
+                * Bump bss entries to _edata + dtb size
                 */
 1:             ldr     r1, [r11, #0]           @ relocate entries in the GOT
-               add     r1, r1, r0              @ table.  This fixes up the
-               str     r1, [r11], #4           @ C references.
+               add     r1, r1, r0              @ This fixes up C references
+               cmp     r1, r2                  @ if entry >= bss_start &&
+               cmphs   r3, r1                  @       bss_end > entry
+               addhi   r1, r1, r5              @    entry += dtb size
+               str     r1, [r11], #4           @ next entry
                cmp     r11, r12
                blo     1b
+
+               /* bump our bss pointers too */
+               add     r2, r2, r5
+               add     r3, r3, r5
+
 #else
 
                /*
diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h
new file mode 100644 (file)
index 0000000..1f4e718
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _ARM_LIBFDT_ENV_H
+#define _ARM_LIBFDT_ENV_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/byteorder.h>
+
+#define fdt16_to_cpu(x)                be16_to_cpu(x)
+#define cpu_to_fdt16(x)                cpu_to_be16(x)
+#define fdt32_to_cpu(x)                be32_to_cpu(x)
+#define cpu_to_fdt32(x)                cpu_to_be32(x)
+#define fdt64_to_cpu(x)                be64_to_cpu(x)
+#define cpu_to_fdt64(x)                cpu_to_be64(x)
+
+#endif
index 832d372..8e2a8fc 100644 (file)
 
 unsigned int __machine_arch_type;
 
-#define _LINUX_STRING_H_
-
 #include <linux/compiler.h>    /* for inline */
-#include <linux/types.h>       /* for size_t */
-#include <linux/stddef.h>      /* for NULL */
+#include <linux/types.h>
 #include <linux/linkage.h>
-#include <asm/string.h>
-
 
 static void putstr(const char *ptr);
 extern void error(char *x);
@@ -101,41 +96,6 @@ static void putstr(const char *ptr)
        flush();
 }
 
-
-void *memcpy(void *__dest, __const void *__src, size_t __n)
-{
-       int i = 0;
-       unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
-
-       for (i = __n >> 3; i > 0; i--) {
-               *d++ = *s++;
-               *d++ = *s++;
-               *d++ = *s++;
-               *d++ = *s++;
-               *d++ = *s++;
-               *d++ = *s++;
-               *d++ = *s++;
-               *d++ = *s++;
-       }
-
-       if (__n & 1 << 2) {
-               *d++ = *s++;
-               *d++ = *s++;
-               *d++ = *s++;
-               *d++ = *s++;
-       }
-
-       if (__n & 1 << 1) {
-               *d++ = *s++;
-               *d++ = *s++;
-       }
-
-       if (__n & 1)
-               *d++ = *s++;
-
-       return __dest;
-}
-
 /*
  * gzip declarations
  */
index b6f61d9..672ae95 100644 (file)
@@ -82,7 +82,7 @@ asmlinkage void mmc_loader(unsigned char *buf, unsigned long len)
 
 
        /* Disable clock to MMC hardware block */
-       __raw_writel(__raw_readl(SMSTPCR3) & (1 << 12), SMSTPCR3);
+       __raw_writel(__raw_readl(SMSTPCR3) | (1 << 12), SMSTPCR3);
 
        mmc_update_progress(MMC_PROGRESS_DONE);
 }
index d403a8b..d279294 100644 (file)
@@ -85,7 +85,7 @@ asmlinkage void mmc_loader(unsigned short *buf, unsigned long len)
                goto err;
 
         /* Disable clock to SDHI1 hardware block */
-        __raw_writel(__raw_readl(SMSTPCR3) & (1 << 13), SMSTPCR3);
+        __raw_writel(__raw_readl(SMSTPCR3) | (1 << 13), SMSTPCR3);
 
        mmc_update_progress(MMC_PROGRESS_DONE);
 
diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c
new file mode 100644 (file)
index 0000000..36e53ef
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/boot/compressed/string.c
+ *
+ * Small subset of simple string routines
+ */
+
+#include <linux/string.h>
+
+void *memcpy(void *__dest, __const void *__src, size_t __n)
+{
+       int i = 0;
+       unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
+
+       for (i = __n >> 3; i > 0; i--) {
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+       }
+
+       if (__n & 1 << 2) {
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+       }
+
+       if (__n & 1 << 1) {
+               *d++ = *s++;
+               *d++ = *s++;
+       }
+
+       if (__n & 1)
+               *d++ = *s++;
+
+       return __dest;
+}
+
+void *memmove(void *__dest, __const void *__src, size_t count)
+{
+       unsigned char *d = __dest;
+       const unsigned char *s = __src;
+
+       if (__dest == __src)
+               return __dest;
+
+       if (__dest < __src)
+               return memcpy(__dest, __src, count);
+
+       while (count--)
+               d[count] = s[count];
+       return __dest;
+}
+
+size_t strlen(const char *s)
+{
+       const char *sc = s;
+
+       while (*sc != '\0')
+               sc++;
+       return sc - s;
+}
+
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+       const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
+       int res = 0;
+
+       while (su1 < end) {
+               res = *su1++ - *su2++;
+               if (res)
+                       break;
+       }
+       return res;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+       unsigned char c1, c2;
+       int res = 0;
+
+       do {
+               c1 = *cs++;
+               c2 = *ct++;
+               res = c1 - c2;
+               if (res)
+                       break;
+       } while (c1);
+       return res;
+}
+
+void *memchr(const void *s, int c, size_t count)
+{
+       const unsigned char *p = s;
+
+       while (count--)
+               if ((unsigned char)c == *p++)
+                       return (void *)(p - 1);
+       return NULL;
+}
+
+char *strchr(const char *s, int c)
+{
+       while (*s != (char)c)
+               if (*s++ == '\0')
+                       return NULL;
+       return (char *)s;
+}
+
+#undef memset
+
+void *memset(void *s, int c, size_t count)
+{
+       char *xs = s;
+       while (count--)
+               *xs++ = c;
+       return s;
+}
+
+void __memzero(void *s, size_t count)
+{
+       memset(s, 0, count);
+}
index 4e72883..4919f2a 100644 (file)
@@ -51,6 +51,10 @@ SECTIONS
   _got_start = .;
   .got                 : { *(.got) }
   _got_end = .;
+
+  /* ensure the zImage file size is always a multiple of 64 bits */
+  /* (without a dummy byte, ld just ignores the empty section) */
+  .pad                 : { BYTE(0); . = ALIGN(8); }
   _edata = .;
 
   . = BSS_START;
index 7a21d0b..7f27fab 100644 (file)
@@ -205,6 +205,13 @@ extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *,
 int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
                void *, dma_addr_t, size_t);
 
+/*
+ * This can be called during boot to increase the size of the consistent
+ * DMA region above it's default value of 2MB. It must be called before the
+ * memory allocator is initialised, i.e. before any core_initcall.
+ */
+extern void __init init_consistent_dma_size(unsigned long size);
+
 
 #ifdef CONFIG_DMABOUNCE
 /*
index bfa706f..99a6ed7 100644 (file)
 #define L2X0_CLEAN_INV_LINE_PA         0x7F0
 #define L2X0_CLEAN_INV_LINE_IDX                0x7F8
 #define L2X0_CLEAN_INV_WAY             0x7FC
-#define L2X0_LOCKDOWN_WAY_D            0x900
-#define L2X0_LOCKDOWN_WAY_I            0x904
+/*
+ * The lockdown registers repeat 8 times for L310, the L210 has only one
+ * D and one I lockdown register at 0x0900 and 0x0904.
+ */
+#define L2X0_LOCKDOWN_WAY_D_BASE       0x900
+#define L2X0_LOCKDOWN_WAY_I_BASE       0x904
+#define L2X0_LOCKDOWN_STRIDE           0x08
 #define L2X0_TEST_OPERATION            0xF00
 #define L2X0_LINE_DATA                 0xF10
 #define L2X0_LINE_TAG                  0xF30
index f389b27..c190bc9 100644 (file)
@@ -50,6 +50,7 @@ static inline void decode_ctrl_reg(u32 reg,
 #define ARM_DEBUG_ARCH_V6_1    2
 #define ARM_DEBUG_ARCH_V7_ECP14        3
 #define ARM_DEBUG_ARCH_V7_MM   4
+#define ARM_DEBUG_ARCH_V7_1    5
 
 /* Breakpoint */
 #define ARM_BREAKPOINT_EXECUTE 0
@@ -57,6 +58,7 @@ static inline void decode_ctrl_reg(u32 reg,
 /* Watchpoints */
 #define ARM_BREAKPOINT_LOAD    1
 #define ARM_BREAKPOINT_STORE   2
+#define ARM_FSR_ACCESS_MASK    (1 << 11)
 
 /* Privilege Levels */
 #define ARM_BREAKPOINT_PRIV    1
index 217aa19..727da11 100644 (file)
@@ -17,7 +17,7 @@ struct sys_timer;
 struct machine_desc {
        unsigned int            nr;             /* architecture number  */
        const char              *name;          /* architecture name    */
-       unsigned long           boot_params;    /* tagged list          */
+       unsigned long           atag_offset;    /* tagged list (relative) */
        const char              **dt_compat;    /* array of device tree
                                                 * 'compatible' strings */
 
index b8de516..652fccc 100644 (file)
  */
 #define IOREMAP_MAX_ORDER      24
 
-/*
- * Size of DMA-consistent memory region.  Must be multiple of 2M,
- * between 2MB and 14MB inclusive.
- */
-#ifndef CONSISTENT_DMA_SIZE
-#define CONSISTENT_DMA_SIZE    SZ_2M
-#endif
-
 #define CONSISTENT_END         (0xffe00000UL)
-#define CONSISTENT_BASE                (CONSISTENT_END - CONSISTENT_DMA_SIZE)
 
 #else /* CONFIG_MMU */
 
index b7e82c4..71d99b8 100644 (file)
 #define __ARM_PMU_H__
 
 #include <linux/interrupt.h>
+#include <linux/perf_event.h>
 
+/*
+ * Types of PMUs that can be accessed directly and require mutual
+ * exclusion between profiling tools.
+ */
 enum arm_pmu_type {
        ARM_PMU_DEVICE_CPU      = 0,
        ARM_NUM_PMU_DEVICES,
@@ -37,21 +42,17 @@ struct arm_pmu_platdata {
  * reserve_pmu() - reserve the hardware performance counters
  *
  * Reserve the hardware performance counters in the system for exclusive use.
- * The platform_device for the system is returned on success, ERR_PTR()
- * encoded error on failure.
+ * Returns 0 on success or -EBUSY if the lock is already held.
  */
-extern struct platform_device *
+extern int
 reserve_pmu(enum arm_pmu_type type);
 
 /**
  * release_pmu() - Relinquish control of the performance counters
  *
  * Release the performance counters and allow someone else to use them.
- * Callers must have disabled the counters and released IRQs before calling
- * this. The platform_device returned from reserve_pmu() must be passed as
- * a cookie.
  */
-extern int
+extern void
 release_pmu(enum arm_pmu_type type);
 
 /**
@@ -68,24 +69,78 @@ init_pmu(enum arm_pmu_type type);
 
 #include <linux/err.h>
 
-static inline struct platform_device *
-reserve_pmu(enum arm_pmu_type type)
-{
-       return ERR_PTR(-ENODEV);
-}
-
 static inline int
-release_pmu(enum arm_pmu_type type)
+reserve_pmu(enum arm_pmu_type type)
 {
        return -ENODEV;
 }
 
-static inline int
-init_pmu(enum arm_pmu_type type)
-{
-       return -ENODEV;
-}
+static inline void
+release_pmu(enum arm_pmu_type type)    { }
 
 #endif /* CONFIG_CPU_HAS_PMU */
 
+#ifdef CONFIG_HW_PERF_EVENTS
+
+/* The events for a given PMU register set. */
+struct pmu_hw_events {
+       /*
+        * The events that are active on the PMU for the given index.
+        */
+       struct perf_event       **events;
+
+       /*
+        * A 1 bit for an index indicates that the counter is being used for
+        * an event. A 0 means that the counter can be used.
+        */
+       unsigned long           *used_mask;
+
+       /*
+        * Hardware lock to serialize accesses to PMU registers. Needed for the
+        * read/modify/write sequences.
+        */
+       raw_spinlock_t          pmu_lock;
+};
+
+struct arm_pmu {
+       struct pmu      pmu;
+       enum arm_perf_pmu_ids id;
+       enum arm_pmu_type type;
+       cpumask_t       active_irqs;
+       const char      *name;
+       irqreturn_t     (*handle_irq)(int irq_num, void *dev);
+       void            (*enable)(struct hw_perf_event *evt, int idx);
+       void            (*disable)(struct hw_perf_event *evt, int idx);
+       int             (*get_event_idx)(struct pmu_hw_events *hw_events,
+                                        struct hw_perf_event *hwc);
+       int             (*set_event_filter)(struct hw_perf_event *evt,
+                                           struct perf_event_attr *attr);
+       u32             (*read_counter)(int idx);
+       void            (*write_counter)(int idx, u32 val);
+       void            (*start)(void);
+       void            (*stop)(void);
+       void            (*reset)(void *);
+       int             (*map_event)(struct perf_event *event);
+       int             num_events;
+       atomic_t        active_events;
+       struct mutex    reserve_mutex;
+       u64             max_period;
+       struct platform_device  *plat_device;
+       struct pmu_hw_events    *(*get_hw_events)(void);
+};
+
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+
+u64 armpmu_event_update(struct perf_event *event,
+                       struct hw_perf_event *hwc,
+                       int idx, int overflow);
+
+int armpmu_event_set_period(struct perf_event *event,
+                           struct hw_perf_event *hwc,
+                           int idx);
+
+#endif /* CONFIG_HW_PERF_EVENTS */
+
 #endif /* __ARM_PMU_H__ */
index 787b888..8fa83f5 100644 (file)
@@ -43,6 +43,13 @@ obj-$(CONFIG_KPROBES)                += kprobes-thumb.o
 else
 obj-$(CONFIG_KPROBES)          += kprobes-arm.o
 endif
+obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o
+test-kprobes-objs              := kprobes-test.o
+ifdef CONFIG_THUMB2_KERNEL
+test-kprobes-objs              += kprobes-test-thumb.o
+else
+test-kprobes-objs              += kprobes-test-arm.o
+endif
 obj-$(CONFIG_ATAGS_PROC)       += atags.o
 obj-$(CONFIG_OABI_COMPAT)      += sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)      += thumbee.o
index 80f7896..9943e9e 100644 (file)
                CALL(sys_ni_syscall)            /* vm86 */
                CALL(sys_ni_syscall)            /* was sys_query_module */
                CALL(sys_poll)
-               CALL(sys_nfsservctl)
+               CALL(sys_ni_syscall)            /* was nfsservctl */
 /* 170 */      CALL(sys_setresgid16)
                CALL(sys_getresgid16)
                CALL(sys_prctl)
index a927ca1..5a46225 100644 (file)
@@ -45,7 +45,6 @@ static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
 
 /* Number of BRP/WRP registers on this CPU. */
 static int core_num_brps;
-static int core_num_reserved_brps;
 static int core_num_wrps;
 
 /* Debug architecture version. */
@@ -137,10 +136,11 @@ static u8 get_debug_arch(void)
        u32 didr;
 
        /* Do we implement the extended CPUID interface? */
-       if (WARN_ONCE((((read_cpuid_id() >> 16) & 0xf) != 0xf),
-           "CPUID feature registers not supported. "
-           "Assuming v6 debug is present.\n"))
+       if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
+               pr_warning("CPUID feature registers not supported. "
+                          "Assuming v6 debug is present.\n");
                return ARM_DEBUG_ARCH_V6;
+       }
 
        ARM_DBG_READ(c0, 0, didr);
        return (didr >> 16) & 0xf;
@@ -154,10 +154,21 @@ u8 arch_get_debug_arch(void)
 static int debug_arch_supported(void)
 {
        u8 arch = get_debug_arch();
-       return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14;
+
+       /* We don't support the memory-mapped interface. */
+       return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) ||
+               arch >= ARM_DEBUG_ARCH_V7_1;
+}
+
+/* Determine number of WRP registers available. */
+static int get_num_wrp_resources(void)
+{
+       u32 didr;
+       ARM_DBG_READ(c0, 0, didr);
+       return ((didr >> 28) & 0xf) + 1;
 }
 
-/* Determine number of BRP register available. */
+/* Determine number of BRP registers available. */
 static int get_num_brp_resources(void)
 {
        u32 didr;
@@ -176,9 +187,10 @@ static int core_has_mismatch_brps(void)
 static int get_num_wrps(void)
 {
        /*
-        * FIXME: When a watchpoint fires, the only way to work out which
-        * watchpoint it was is by disassembling the faulting instruction
-        * and working out the address of the memory access.
+        * On debug architectures prior to 7.1, when a watchpoint fires, the
+        * only way to work out which watchpoint it was is by disassembling
+        * the faulting instruction and working out the address of the memory
+        * access.
         *
         * Furthermore, we can only do this if the watchpoint was precise
         * since imprecise watchpoints prevent us from calculating register
@@ -192,36 +204,17 @@ static int get_num_wrps(void)
         * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
         * that it is set on some implementations].
         */
+       if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1)
+               return 1;
 
-#if 0
-       int wrps;
-       u32 didr;
-       ARM_DBG_READ(c0, 0, didr);
-       wrps = ((didr >> 28) & 0xf) + 1;
-#endif
-       int wrps = 1;
-
-       if (core_has_mismatch_brps() && wrps >= get_num_brp_resources())
-               wrps = get_num_brp_resources() - 1;
-
-       return wrps;
-}
-
-/* We reserve one breakpoint for each watchpoint. */
-static int get_num_reserved_brps(void)
-{
-       if (core_has_mismatch_brps())
-               return get_num_wrps();
-       return 0;
+       return get_num_wrp_resources();
 }
 
 /* Determine number of usable BRPs available. */
 static int get_num_brps(void)
 {
        int brps = get_num_brp_resources();
-       if (core_has_mismatch_brps())
-               brps -= get_num_reserved_brps();
-       return brps;
+       return core_has_mismatch_brps() ? brps - 1 : brps;
 }
 
 /*
@@ -239,7 +232,7 @@ static int enable_monitor_mode(void)
 
        /* Ensure that halting mode is disabled. */
        if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
-                       "halting debug mode enabled. Unable to access hardware resources.\n")) {
+               "halting debug mode enabled. Unable to access hardware resources.\n")) {
                ret = -EPERM;
                goto out;
        }
@@ -255,6 +248,7 @@ static int enable_monitor_mode(void)
                ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
                break;
        case ARM_DEBUG_ARCH_V7_ECP14:
+       case ARM_DEBUG_ARCH_V7_1:
                ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
                break;
        default:
@@ -346,24 +340,10 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
                val_base = ARM_BASE_BVR;
                slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
                max_slots = core_num_brps;
-               if (info->step_ctrl.enabled) {
-                       /* Override the breakpoint data with the step data. */
-                       addr = info->trigger & ~0x3;
-                       ctrl = encode_ctrl_reg(info->step_ctrl);
-               }
        } else {
                /* Watchpoint */
-               if (info->step_ctrl.enabled) {
-                       /* Install into the reserved breakpoint region. */
-                       ctrl_base = ARM_BASE_BCR + core_num_brps;
-                       val_base = ARM_BASE_BVR + core_num_brps;
-                       /* Override the watchpoint data with the step data. */
-                       addr = info->trigger & ~0x3;
-                       ctrl = encode_ctrl_reg(info->step_ctrl);
-               } else {
-                       ctrl_base = ARM_BASE_WCR;
-                       val_base = ARM_BASE_WVR;
-               }
+               ctrl_base = ARM_BASE_WCR;
+               val_base = ARM_BASE_WVR;
                slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
                max_slots = core_num_wrps;
        }
@@ -382,6 +362,17 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
                goto out;
        }
 
+       /* Override the breakpoint data with the step data. */
+       if (info->step_ctrl.enabled) {
+               addr = info->trigger & ~0x3;
+               ctrl = encode_ctrl_reg(info->step_ctrl);
+               if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE) {
+                       i = 0;
+                       ctrl_base = ARM_BASE_BCR + core_num_brps;
+                       val_base = ARM_BASE_BVR + core_num_brps;
+               }
+       }
+
        /* Setup the address register. */
        write_wb_reg(val_base + i, addr);
 
@@ -405,10 +396,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
                max_slots = core_num_brps;
        } else {
                /* Watchpoint */
-               if (info->step_ctrl.enabled)
-                       base = ARM_BASE_BCR + core_num_brps;
-               else
-                       base = ARM_BASE_WCR;
+               base = ARM_BASE_WCR;
                slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
                max_slots = core_num_wrps;
        }
@@ -426,6 +414,13 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
        if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
                return;
 
+       /* Ensure that we disable the mismatch breakpoint. */
+       if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE &&
+           info->step_ctrl.enabled) {
+               i = 0;
+               base = ARM_BASE_BCR + core_num_brps;
+       }
+
        /* Reset the control register. */
        write_wb_reg(base + i, 0);
 }
@@ -632,10 +627,9 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
         * we can use the mismatch feature as a poor-man's hardware
         * single-step, but this only works for per-task breakpoints.
         */
-       if (WARN_ONCE(!bp->overflow_handler &&
-               (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
-                || !bp->hw.bp_target),
-                       "overflow handler required but none found\n")) {
+       if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) ||
+           !core_has_mismatch_brps() || !bp->hw.bp_target)) {
+               pr_warning("overflow handler required but none found\n");
                ret = -EINVAL;
        }
 out:
@@ -666,34 +660,62 @@ static void disable_single_step(struct perf_event *bp)
        arch_install_hw_breakpoint(bp);
 }
 
-static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
+static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+                              struct pt_regs *regs)
 {
-       int i;
+       int i, access;
+       u32 val, ctrl_reg, alignment_mask;
        struct perf_event *wp, **slots;
        struct arch_hw_breakpoint *info;
+       struct arch_hw_breakpoint_ctrl ctrl;
 
        slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 
-       /* Without a disassembler, we can only handle 1 watchpoint. */
-       BUG_ON(core_num_wrps > 1);
-
        for (i = 0; i < core_num_wrps; ++i) {
                rcu_read_lock();
 
                wp = slots[i];
 
-               if (wp == NULL) {
-                       rcu_read_unlock();
-                       continue;
-               }
+               if (wp == NULL)
+                       goto unlock;
 
+               info = counter_arch_bp(wp);
                /*
-                * The DFAR is an unknown value. Since we only allow a
-                * single watchpoint, we can set the trigger to the lowest
-                * possible faulting address.
+                * The DFAR is an unknown value on debug architectures prior
+                * to 7.1. Since we only allow a single watchpoint on these
+                * older CPUs, we can set the trigger to the lowest possible
+                * faulting address.
                 */
-               info = counter_arch_bp(wp);
-               info->trigger = wp->attr.bp_addr;
+               if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
+                       BUG_ON(i > 0);
+                       info->trigger = wp->attr.bp_addr;
+               } else {
+                       if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+                               alignment_mask = 0x7;
+                       else
+                               alignment_mask = 0x3;
+
+                       /* Check if the watchpoint value matches. */
+                       val = read_wb_reg(ARM_BASE_WVR + i);
+                       if (val != (addr & ~alignment_mask))
+                               goto unlock;
+
+                       /* Possible match, check the byte address select. */
+                       ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
+                       decode_ctrl_reg(ctrl_reg, &ctrl);
+                       if (!((1 << (addr & alignment_mask)) & ctrl.len))
+                               goto unlock;
+
+                       /* Check that the access type matches. */
+                       access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W :
+                                HW_BREAKPOINT_R;
+                       if (!(access & hw_breakpoint_type(wp)))
+                               goto unlock;
+
+                       /* We have a winner. */
+                       info->trigger = addr;
+               }
+
                pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
                perf_bp_event(wp, regs);
 
@@ -705,6 +727,7 @@ static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
                if (!wp->overflow_handler)
                        enable_single_step(wp, instruction_pointer(regs));
 
+unlock:
                rcu_read_unlock();
        }
 }
@@ -717,7 +740,7 @@ static void watchpoint_single_step_handler(unsigned long pc)
 
        slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 
-       for (i = 0; i < core_num_reserved_brps; ++i) {
+       for (i = 0; i < core_num_wrps; ++i) {
                rcu_read_lock();
 
                wp = slots[i];
@@ -820,7 +843,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
        case ARM_ENTRY_ASYNC_WATCHPOINT:
                WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");
        case ARM_ENTRY_SYNC_WATCHPOINT:
-               watchpoint_handler(addr, regs);
+               watchpoint_handler(addr, fsr, regs);
                break;
        default:
                ret = 1; /* Unhandled fault. */
@@ -834,11 +857,31 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
 /*
  * One-time initialisation.
  */
-static void reset_ctrl_regs(void *info)
+static cpumask_t debug_err_mask;
+
+static int debug_reg_trap(struct pt_regs *regs, unsigned int instr)
 {
-       int i, cpu = smp_processor_id();
+       int cpu = smp_processor_id();
+
+       pr_warning("Debug register access (0x%x) caused undefined instruction on CPU %d\n",
+                  instr, cpu);
+
+       /* Set the error flag for this CPU and skip the faulting instruction. */
+       cpumask_set_cpu(cpu, &debug_err_mask);
+       instruction_pointer(regs) += 4;
+       return 0;
+}
+
+static struct undef_hook debug_reg_hook = {
+       .instr_mask     = 0x0fe80f10,
+       .instr_val      = 0x0e000e10,
+       .fn             = debug_reg_trap,
+};
+
+static void reset_ctrl_regs(void *unused)
+{
+       int i, raw_num_brps, err = 0, cpu = smp_processor_id();
        u32 dbg_power;
-       cpumask_t *cpumask = info;
 
        /*
         * v7 debug contains save and restore registers so that debug state
@@ -848,38 +891,52 @@ static void reset_ctrl_regs(void *info)
         * Access Register to avoid taking undefined instruction exceptions
         * later on.
         */
-       if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {
+       switch (debug_arch) {
+       case ARM_DEBUG_ARCH_V7_ECP14:
                /*
                 * Ensure sticky power-down is clear (i.e. debug logic is
                 * powered up).
                 */
                asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
-               if ((dbg_power & 0x1) == 0) {
-                       pr_warning("CPU %d debug is powered down!\n", cpu);
-                       cpumask_or(cpumask, cpumask, cpumask_of(cpu));
-                       return;
-               }
-
+               if ((dbg_power & 0x1) == 0)
+                       err = -EPERM;
+               break;
+       case ARM_DEBUG_ARCH_V7_1:
                /*
-                * Unconditionally clear the lock by writing a value
-                * other than 0xC5ACCE55 to the access register.
+                * Ensure the OS double lock is clear.
                 */
-               asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
-               isb();
+               asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power));
+               if ((dbg_power & 0x1) == 1)
+                       err = -EPERM;
+               break;
+       }
 
-               /*
-                * Clear any configured vector-catch events before
-                * enabling monitor mode.
-                */
-               asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
-               isb();
+       if (err) {
+               pr_warning("CPU %d debug is powered down!\n", cpu);
+               cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
+               return;
        }
 
+       /*
+        * Unconditionally clear the lock by writing a value
+        * other than 0xC5ACCE55 to the access register.
+        */
+       asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
+       isb();
+
+       /*
+        * Clear any configured vector-catch events before
+        * enabling monitor mode.
+        */
+       asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+       isb();
+
        if (enable_monitor_mode())
                return;
 
        /* We must also reset any reserved registers. */
-       for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
+       raw_num_brps = get_num_brp_resources();
+       for (i = 0; i < raw_num_brps; ++i) {
                write_wb_reg(ARM_BASE_BCR + i, 0UL);
                write_wb_reg(ARM_BASE_BVR + i, 0UL);
        }
@@ -895,6 +952,7 @@ static int __cpuinit dbg_reset_notify(struct notifier_block *self,
 {
        if (action == CPU_ONLINE)
                smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
+
        return NOTIFY_OK;
 }
 
@@ -905,7 +963,6 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {
 static int __init arch_hw_breakpoint_init(void)
 {
        u32 dscr;
-       cpumask_t cpumask = { CPU_BITS_NONE };
 
        debug_arch = get_debug_arch();
 
@@ -916,28 +973,31 @@ static int __init arch_hw_breakpoint_init(void)
 
        /* Determine how many BRPs/WRPs are available. */
        core_num_brps = get_num_brps();
-       core_num_reserved_brps = get_num_reserved_brps();
        core_num_wrps = get_num_wrps();
 
-       pr_info("found %d breakpoint and %d watchpoint registers.\n",
-               core_num_brps + core_num_reserved_brps, core_num_wrps);
-
-       if (core_num_reserved_brps)
-               pr_info("%d breakpoint(s) reserved for watchpoint "
-                               "single-step.\n", core_num_reserved_brps);
+       /*
+        * We need to tread carefully here because DBGSWENABLE may be
+        * driven low on this core and there isn't an architected way to
+        * determine that.
+        */
+       register_undef_hook(&debug_reg_hook);
 
        /*
         * Reset the breakpoint resources. We assume that a halting
         * debugger will leave the world in a nice state for us.
         */
-       on_each_cpu(reset_ctrl_regs, &cpumask, 1);
-       if (!cpumask_empty(&cpumask)) {
+       on_each_cpu(reset_ctrl_regs, NULL, 1);
+       unregister_undef_hook(&debug_reg_hook);
+       if (!cpumask_empty(&debug_err_mask)) {
                core_num_brps = 0;
-               core_num_reserved_brps = 0;
                core_num_wrps = 0;
                return 0;
        }
 
+       pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n",
+               core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
+               "", core_num_wrps);
+
        ARM_DBG_READ(c1, 0, dscr);
        if (dscr & ARM_DSCR_HDBGEN) {
                max_watchpoint_len = 4;
index 79203ee..9fe8910 100644 (file)
@@ -60,6 +60,7 @@
 
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
+#include <linux/module.h>
 
 #include "kprobes.h"
 
@@ -971,6 +972,9 @@ const union decode_item kprobe_decode_arm_table[] = {
 
        DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
+#endif
 
 static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c
new file mode 100644 (file)
index 0000000..fc82de8
--- /dev/null
@@ -0,0 +1,1323 @@
+/*
+ * arch/arm/kernel/kprobes-test-arm.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "32"
+
+#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2)  \
+       TESTCASE_START(code1 #reg code2)                        \
+       TEST_ARG_REG(reg, val)                                  \
+       TEST_ARG_REG(14, 99f)                                   \
+       TEST_ARG_END("")                                        \
+       "50:    nop                     \n\t"                   \
+       "1:     "code1 #reg code2"      \n\t"                   \
+       "       bx      lr              \n\t"                   \
+       ".thumb                         \n\t"                   \
+       "3:     adr     lr, 2f          \n\t"                   \
+       "       bx      lr              \n\t"                   \
+       ".arm                           \n\t"                   \
+       "2:     nop                     \n\t"                   \
+       TESTCASE_END
+
+#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2)  \
+       TESTCASE_START(code1 #reg code2)                        \
+       TEST_ARG_PTR(reg, val)                                  \
+       TEST_ARG_REG(14, 99f)                                   \
+       TEST_ARG_MEM(15, 3f+1)                                  \
+       TEST_ARG_END("")                                        \
+       "50:    nop                     \n\t"                   \
+       "1:     "code1 #reg code2"      \n\t"                   \
+       "       bx      lr              \n\t"                   \
+       ".thumb                         \n\t"                   \
+       "3:     adr     lr, 2f          \n\t"                   \
+       "       bx      lr              \n\t"                   \
+       ".arm                           \n\t"                   \
+       "2:     nop                     \n\t"                   \
+       TESTCASE_END
+
+
+void kprobe_arm_test_cases(void)
+{
+       kprobe_test_flags = 0;
+
+       TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)")
+
+#define _DATA_PROCESSING_DNM(op,s,val)                                         \
+       TEST_RR(  op "eq" s "   r0,  r",1, VAL1,", r",2, val, "")               \
+       TEST_RR(  op "ne" s "   r1,  r",1, VAL1,", r",2, val, ", lsl #3")       \
+       TEST_RR(  op "cs" s "   r2,  r",3, VAL1,", r",2, val, ", lsr #4")       \
+       TEST_RR(  op "cc" s "   r3,  r",3, VAL1,", r",2, val, ", asr #5")       \
+       TEST_RR(  op "mi" s "   r4,  r",5, VAL1,", r",2, N(val),", asr #6")     \
+       TEST_RR(  op "pl" s "   r5,  r",5, VAL1,", r",2, val, ", ror #7")       \
+       TEST_RR(  op "vs" s "   r6,  r",7, VAL1,", r",2, val, ", rrx")          \
+       TEST_R(   op "vc" s "   r6,  r",7, VAL1,", pc, lsl #3")                 \
+       TEST_R(   op "vc" s "   r6,  r",7, VAL1,", sp, lsr #4")                 \
+       TEST_R(   op "vc" s "   r6,  pc, r",7, VAL1,", asr #5")                 \
+       TEST_R(   op "vc" s "   r6,  sp, r",7, VAL1,", ror #6")                 \
+       TEST_RRR( op "hi" s "   r8,  r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\
+       TEST_RRR( op "ls" s "   r9,  r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\
+       TEST_RRR( op "ge" s "   r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\
+       TEST_RRR( op "lt" s "   r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\
+       TEST_RR(  op "gt" s "   r12, r13"       ", r",14,val, ", ror r",14,7,"")\
+       TEST_RR(  op "le" s "   r14, r",0, val, ", r13"       ", lsl r",14,8,"")\
+       TEST_RR(  op s "        r12, pc"        ", r",14,val, ", ror r",14,7,"")\
+       TEST_RR(  op s "        r14, r",0, val, ", pc"        ", lsl r",14,8,"")\
+       TEST_R(   op "eq" s "   r0,  r",11,VAL1,", #0xf5")                      \
+       TEST_R(   op "ne" s "   r11, r",0, VAL1,", #0xf5000000")                \
+       TEST_R(   op s "        r7,  r",8, VAL2,", #0x000af000")                \
+       TEST(     op s "        r4,  pc"        ", #0x00005a00")
+
+#define DATA_PROCESSING_DNM(op,val)            \
+       _DATA_PROCESSING_DNM(op,"",val)         \
+       _DATA_PROCESSING_DNM(op,"s",val)
+
+#define DATA_PROCESSING_NM(op,val)                                             \
+       TEST_RR(  op "ne        r",1, VAL1,", r",2, val, "")                    \
+       TEST_RR(  op "eq        r",1, VAL1,", r",2, val, ", lsl #3")            \
+       TEST_RR(  op "cc        r",3, VAL1,", r",2, val, ", lsr #4")            \
+       TEST_RR(  op "cs        r",3, VAL1,", r",2, val, ", asr #5")            \
+       TEST_RR(  op "pl        r",5, VAL1,", r",2, N(val),", asr #6")          \
+       TEST_RR(  op "mi        r",5, VAL1,", r",2, val, ", ror #7")            \
+       TEST_RR(  op "vc        r",7, VAL1,", r",2, val, ", rrx")               \
+       TEST_R (  op "vs        r",7, VAL1,", pc, lsl #3")                      \
+       TEST_R (  op "vs        r",7, VAL1,", sp, lsr #4")                      \
+       TEST_R(   op "vs        pc, r",7, VAL1,", asr #5")                      \
+       TEST_R(   op "vs        sp, r",7, VAL1,", ror #6")                      \
+       TEST_RRR( op "ls        r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")     \
+       TEST_RRR( op "hi        r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")     \
+       TEST_RRR( op "lt        r",11,VAL1,", r",14,val, ", asr r",7, 5,"")     \
+       TEST_RRR( op "ge        r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")   \
+       TEST_RR(  op "le        r13"       ", r",14,val, ", ror r",14,7,"")     \
+       TEST_RR(  op "gt        r",0, val, ", r13"       ", lsl r",14,8,"")     \
+       TEST_RR(  op "  pc"        ", r",14,val, ", ror r",14,7,"")             \
+       TEST_RR(  op "  r",0, val, ", pc"        ", lsl r",14,8,"")             \
+       TEST_R(   op "eq        r",11,VAL1,", #0xf5")                           \
+       TEST_R(   op "ne        r",0, VAL1,", #0xf5000000")                     \
+       TEST_R(   op "  r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING_DM(op,s,val)                                  \
+       TEST_R(   op "eq" s "   r0,  r",1, val, "")                     \
+       TEST_R(   op "ne" s "   r1,  r",1, val, ", lsl #3")             \
+       TEST_R(   op "cs" s "   r2,  r",3, val, ", lsr #4")             \
+       TEST_R(   op "cc" s "   r3,  r",3, val, ", asr #5")             \
+       TEST_R(   op "mi" s "   r4,  r",5, N(val),", asr #6")           \
+       TEST_R(   op "pl" s "   r5,  r",5, val, ", ror #7")             \
+       TEST_R(   op "vs" s "   r6,  r",10,val, ", rrx")                \
+       TEST(     op "vs" s "   r7,  pc, lsl #3")                       \
+       TEST(     op "vs" s "   r7,  sp, lsr #4")                       \
+       TEST_RR(  op "vc" s "   r8,  r",7, val, ", lsl r",0, 3,"")      \
+       TEST_RR(  op "hi" s "   r9,  r",9, val, ", lsr r",7, 4,"")      \
+       TEST_RR(  op "ls" s "   r10, r",9, val, ", asr r",7, 5,"")      \
+       TEST_RR(  op "ge" s "   r11, r",11,N(val),", asr r",7, 6,"")    \
+       TEST_RR(  op "lt" s "   r12, r",11,val, ", ror r",14,7,"")      \
+       TEST_R(   op "gt" s "   r14, r13"       ", lsl r",14,8,"")      \
+       TEST_R(   op "le" s "   r14, pc"        ", lsl r",14,8,"")      \
+       TEST(     op "eq" s "   r0,  #0xf5")                            \
+       TEST(     op "ne" s "   r11, #0xf5000000")                      \
+       TEST(     op s "        r7,  #0x000af000")                      \
+       TEST(     op s "        r4,  #0x00005a00")
+
+#define DATA_PROCESSING_DM(op,val)             \
+       _DATA_PROCESSING_DM(op,"",val)          \
+       _DATA_PROCESSING_DM(op,"s",val)
+
+       DATA_PROCESSING_DNM("and",0xf00f00ff)
+       DATA_PROCESSING_DNM("eor",0xf00f00ff)
+       DATA_PROCESSING_DNM("sub",VAL2)
+       DATA_PROCESSING_DNM("rsb",VAL2)
+       DATA_PROCESSING_DNM("add",VAL2)
+       DATA_PROCESSING_DNM("adc",VAL2)
+       DATA_PROCESSING_DNM("sbc",VAL2)
+       DATA_PROCESSING_DNM("rsc",VAL2)
+       DATA_PROCESSING_NM("tst",0xf00f00ff)
+       DATA_PROCESSING_NM("teq",0xf00f00ff)
+       DATA_PROCESSING_NM("cmp",VAL2)
+       DATA_PROCESSING_NM("cmn",VAL2)
+       DATA_PROCESSING_DNM("orr",0xf00f00ff)
+       DATA_PROCESSING_DM("mov",VAL2)
+       DATA_PROCESSING_DNM("bic",0xf00f00ff)
+       DATA_PROCESSING_DM("mvn",VAL2)
+
+       TEST("mov       ip, sp") /* This has special case emulation code */
+
+       TEST_SUPPORTED("mov     pc, #0x1000");
+       TEST_SUPPORTED("mov     sp, #0x1000");
+       TEST_SUPPORTED("cmp     pc, #0x1000");
+       TEST_SUPPORTED("cmp     sp, #0x1000");
+
+       /* Data-processing with PC as shift*/
+       TEST_UNSUPPORTED(".word 0xe15c0f1e      @ cmp   r12, r14, asl pc")
+       TEST_UNSUPPORTED(".word 0xe1a0cf1e      @ mov   r12, r14, asl pc")
+       TEST_UNSUPPORTED(".word 0xe08caf1e      @ add   r10, r12, r14, asl pc")
+
+       /* Data-processing with PC as shift*/
+       TEST_UNSUPPORTED("movs  pc, r1")
+       TEST_UNSUPPORTED("movs  pc, r1, lsl r2")
+       TEST_UNSUPPORTED("movs  pc, #0x10000")
+       TEST_UNSUPPORTED("adds  pc, lr, r1")
+       TEST_UNSUPPORTED("adds  pc, lr, r1, lsl r2")
+       TEST_UNSUPPORTED("adds  pc, lr, #4")
+
+       /* Data-processing with SP as target */
+       TEST("add       sp, sp, #16")
+       TEST("sub       sp, sp, #8")
+       TEST("bic       sp, sp, #0x20")
+       TEST("orr       sp, sp, #0x20")
+       TEST_PR( "add   sp, r",10,0,", r",11,4,"")
+       TEST_PRR("add   sp, r",10,0,", r",11,4,", asl r",12,1,"")
+       TEST_P(  "mov   sp, r",10,0,"")
+       TEST_PR( "mov   sp, r",10,0,", asl r",12,0,"")
+
+       /* Data-processing with PC as target */
+       TEST_BF(   "add pc, pc, #2f-1b-8")
+       TEST_BF_R ("add pc, pc, r",14,2f-1f-8,"")
+       TEST_BF_R ("add pc, r",14,2f-1f-8,", pc")
+       TEST_BF_R ("mov pc, r",0,2f,"")
+       TEST_BF_RR("mov pc, r",0,2f,", asl r",1,0,"")
+       TEST_BB(   "sub pc, pc, #1b-2b+8")
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_BB(   "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */
+#endif
+       TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"")
+       TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc")
+       TEST_RR(   "add pc, pc, r",10,-2,", asl r",11,1,"")
+#ifdef CONFIG_THUMB2_KERNEL
+       TEST_ARM_TO_THUMB_INTERWORK_R("add      pc, pc, r",0,3f-1f-8+1,"")
+       TEST_ARM_TO_THUMB_INTERWORK_R("sub      pc, r",0,3f+8+1,", #8")
+#endif
+       TEST_GROUP("Miscellaneous instructions")
+
+       TEST("mrs       r0, cpsr")
+       TEST("mrspl     r7, cpsr")
+       TEST("mrs       r14, cpsr")
+       TEST_UNSUPPORTED(".word 0xe10ff000      @ mrs r15, cpsr")
+       TEST_UNSUPPORTED("mrs   r0, spsr")
+       TEST_UNSUPPORTED("mrs   lr, spsr")
+
+       TEST_UNSUPPORTED("msr   cpsr, r0")
+       TEST_UNSUPPORTED("msr   cpsr_f, lr")
+       TEST_UNSUPPORTED("msr   spsr, r0")
+
+       TEST_BF_R("bx   r",0,2f,"")
+       TEST_BB_R("bx   r",7,2f,"")
+       TEST_BF_R("bxeq r",14,2f,"")
+
+       TEST_R("clz     r0, r",0, 0x0,"")
+       TEST_R("clzeq   r7, r",14,0x1,"")
+       TEST_R("clz     lr, r",7, 0xffffffff,"")
+       TEST(  "clz     r4, sp")
+       TEST_UNSUPPORTED(".word 0x016fff10      @ clz pc, r0")
+       TEST_UNSUPPORTED(".word 0x016f0f1f      @ clz r0, pc")
+
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_UNSUPPORTED("bxj   r0")
+#endif
+
+       TEST_BF_R("blx  r",0,2f,"")
+       TEST_BB_R("blx  r",7,2f,"")
+       TEST_BF_R("blxeq        r",14,2f,"")
+       TEST_UNSUPPORTED(".word 0x0120003f      @ blx pc")
+
+       TEST_RR(   "qadd        r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(   "qaddvs      lr, r",9, VAL2,", r",8, VAL1,"")
+       TEST_R(    "qadd        lr, r",9, VAL2,", r13")
+       TEST_RR(   "qsub        r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(   "qsubvs      lr, r",9, VAL2,", r",8, VAL1,"")
+       TEST_R(    "qsub        lr, r",9, VAL2,", r13")
+       TEST_RR(   "qdadd       r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(   "qdaddvs     lr, r",9, VAL2,", r",8, VAL1,"")
+       TEST_R(    "qdadd       lr, r",9, VAL2,", r13")
+       TEST_RR(   "qdsub       r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(   "qdsubvs     lr, r",9, VAL2,", r",8, VAL1,"")
+       TEST_R(    "qdsub       lr, r",9, VAL2,", r13")
+       TEST_UNSUPPORTED(".word 0xe101f050      @ qadd pc, r0, r1")
+       TEST_UNSUPPORTED(".word 0xe121f050      @ qsub pc, r0, r1")
+       TEST_UNSUPPORTED(".word 0xe141f050      @ qdadd pc, r0, r1")
+       TEST_UNSUPPORTED(".word 0xe161f050      @ qdsub pc, r0, r1")
+       TEST_UNSUPPORTED(".word 0xe16f2050      @ qdsub r2, r0, pc")
+       TEST_UNSUPPORTED(".word 0xe161205f      @ qdsub r2, pc, r1")
+
+       TEST_UNSUPPORTED("bkpt  0xffff")
+       TEST_UNSUPPORTED("bkpt  0x0000")
+
+       TEST_UNSUPPORTED(".word 0xe1600070 @ smc #0")
+
+       TEST_GROUP("Halfword multiply and multiply-accumulate")
+
+       TEST_RRR(    "smlabb    r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(    "smlabbge  r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(     "smlabb    lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe10f3281 @ smlabb pc, r1, r2, r3")
+       TEST_RRR(    "smlatb    r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(    "smlatbge  r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(     "smlatb    lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe10f32a1 @ smlatb pc, r1, r2, r3")
+       TEST_RRR(    "smlabt    r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(    "smlabtge  r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(     "smlabt    lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe10f32c1 @ smlabt pc, r1, r2, r3")
+       TEST_RRR(    "smlatt    r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(    "smlattge  r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(     "smlatt    lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe10f32e1 @ smlatt pc, r1, r2, r3")
+
+       TEST_RRR(    "smlawb    r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(    "smlawbge  r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(     "smlawb    lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe12f3281 @ smlawb pc, r1, r2, r3")
+       TEST_RRR(    "smlawt    r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(    "smlawtge  r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(     "smlawt    lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe12f32c1 @ smlawt pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe12032cf @ smlawt r0, pc, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe1203fc1 @ smlawt r0, r1, pc, r3")
+       TEST_UNSUPPORTED(".word 0xe120f2c1 @ smlawt r0, r1, r2, pc")
+
+       TEST_RR(    "smulwb     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulwbge   r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_R(     "smulwb     lr, r",1, VAL2,", r13")
+       TEST_UNSUPPORTED(".word 0xe12f02a1 @ smulwb pc, r1, r2")
+       TEST_RR(    "smulwt     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulwtge   r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_R(     "smulwt     lr, r",1, VAL2,", r13")
+       TEST_UNSUPPORTED(".word 0xe12f02e1 @ smulwt pc, r1, r2")
+
+       TEST_RRRR(  "smlalbb    r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR(  "smlalbble  r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRR(   "smlalbb    r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+       TEST_UNSUPPORTED(".word 0xe14f1382 @ smlalbb pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe141f382 @ smlalbb r1, pc, r2, r3")
+       TEST_RRRR(  "smlaltb    r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR(  "smlaltble  r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRR(   "smlaltb    r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+       TEST_UNSUPPORTED(".word 0xe14f13a2 @ smlaltb pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe141f3a2 @ smlaltb r1, pc, r2, r3")
+       TEST_RRRR(  "smlalbt    r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR(  "smlalbtle  r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRR(   "smlalbt    r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+       TEST_UNSUPPORTED(".word 0xe14f13c2 @ smlalbt pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe141f3c2 @ smlalbt r1, pc, r2, r3")
+       TEST_RRRR(  "smlaltt    r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR(  "smlalttle  r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRR(   "smlaltt    r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+       TEST_UNSUPPORTED(".word 0xe14f13e2 @ smlalbb pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe140f3e2 @ smlalbb r0, pc, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe14013ef @ smlalbb r0, r1, pc, r3")
+       TEST_UNSUPPORTED(".word 0xe1401fe2 @ smlalbb r0, r1, r2, pc")
+
+       TEST_RR(    "smulbb     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulbbge   r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_R(     "smulbb     lr, r",1, VAL2,", r13")
+       TEST_UNSUPPORTED(".word 0xe16f0281 @ smulbb pc, r1, r2")
+       TEST_RR(    "smultb     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smultbge   r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_R(     "smultb     lr, r",1, VAL2,", r13")
+       TEST_UNSUPPORTED(".word 0xe16f02a1 @ smultb pc, r1, r2")
+       TEST_RR(    "smulbt     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulbtge   r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_R(     "smulbt     lr, r",1, VAL2,", r13")
+       TEST_UNSUPPORTED(".word 0xe16f02c1 @ smultb pc, r1, r2")
+       TEST_RR(    "smultt     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulttge   r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_R(     "smultt     lr, r",1, VAL2,", r13")
+       TEST_UNSUPPORTED(".word 0xe16f02e1 @ smultt pc, r1, r2")
+       TEST_UNSUPPORTED(".word 0xe16002ef @ smultt r0, pc, r2")
+       TEST_UNSUPPORTED(".word 0xe1600fe1 @ smultt r0, r1, pc")
+
+       TEST_GROUP("Multiply and multiply-accumulate")
+
+       TEST_RR(    "mul        r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "mulls      r7, r",8, VAL2,", r",9, VAL2,"")
+       TEST_R(     "mul        lr, r",4, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe00f0291 @ mul pc, r1, r2")
+       TEST_UNSUPPORTED(".word 0xe000029f @ mul r0, pc, r2")
+       TEST_UNSUPPORTED(".word 0xe0000f91 @ mul r0, r1, pc")
+       TEST_RR(    "muls       r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "mullss     r7, r",8, VAL2,", r",9, VAL2,"")
+       TEST_R(     "muls       lr, r",4, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe01f0291 @ muls pc, r1, r2")
+
+       TEST_RRR(    "mla       r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(    "mlahi     r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(     "mla       lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe02f3291 @ mla pc, r1, r2, r3")
+       TEST_RRR(    "mlas      r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(    "mlahis    r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(     "mlas      lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe03f3291 @ mlas pc, r1, r2, r3")
+
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_RR(  "umaal        r0, r1, r",2, VAL1,", r",3, VAL2,"")
+       TEST_RR(  "umaalls      r7, r8, r",9, VAL2,", r",10, VAL1,"")
+       TEST_R(   "umaal        lr, r12, r",11,VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe041f392 @ umaal pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
+       TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+
+       TEST_RRR(  "mls         r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(  "mlshi       r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(   "mls         lr, r",1, VAL2,", r",2, VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe06f3291 @ mls pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe060329f @ mls r0, pc, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0603f91 @ mls r0, r1, pc, r3")
+       TEST_UNSUPPORTED(".word 0xe060f291 @ mls r0, r1, r2, pc")
+#endif
+
+       TEST_UNSUPPORTED(".word 0xe0700090 @ undef")
+       TEST_UNSUPPORTED(".word 0xe07fff9f @ undef")
+
+       TEST_RR(  "umull        r0, r1, r",2, VAL1,", r",3, VAL2,"")
+       TEST_RR(  "umullls      r7, r8, r",9, VAL2,", r",10, VAL1,"")
+       TEST_R(   "umull        lr, r12, r",11,VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe081f392 @ umull pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe08f1392 @ umull r1, pc, r2, r3")
+       TEST_RR(  "umulls       r0, r1, r",2, VAL1,", r",3, VAL2,"")
+       TEST_RR(  "umulllss     r7, r8, r",9, VAL2,", r",10, VAL1,"")
+       TEST_R(   "umulls       lr, r12, r",11,VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe091f392 @ umulls pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe09f1392 @ umulls r1, pc, r2, r3")
+
+       TEST_RRRR(  "umlal      r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR(  "umlalle    r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRR(   "umlal      r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+       TEST_UNSUPPORTED(".word 0xe0af1392 @ umlal pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0a1f392 @ umlal r1, pc, r2, r3")
+       TEST_RRRR(  "umlals     r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR(  "umlalles   r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRR(   "umlals     r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+       TEST_UNSUPPORTED(".word 0xe0bf1392 @ umlals pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0b1f392 @ umlals r1, pc, r2, r3")
+
+       TEST_RR(  "smull        r0, r1, r",2, VAL1,", r",3, VAL2,"")
+       TEST_RR(  "smullls      r7, r8, r",9, VAL2,", r",10, VAL1,"")
+       TEST_R(   "smull        lr, r12, r",11,VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe0c1f392 @ smull pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0cf1392 @ smull r1, pc, r2, r3")
+       TEST_RR(  "smulls       r0, r1, r",2, VAL1,", r",3, VAL2,"")
+       TEST_RR(  "smulllss     r7, r8, r",9, VAL2,", r",10, VAL1,"")
+       TEST_R(   "smulls       lr, r12, r",11,VAL3,", r13")
+       TEST_UNSUPPORTED(".word 0xe0d1f392 @ smulls pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0df1392 @ smulls r1, pc, r2, r3")
+
+       TEST_RRRR(  "smlal      r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR(  "smlalle    r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRR(   "smlal      r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+       TEST_UNSUPPORTED(".word 0xe0ef1392 @ smlal pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0e1f392 @ smlal r1, pc, r2, r3")
+       TEST_RRRR(  "smlals     r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR(  "smlalles   r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRR(   "smlals     r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+       TEST_UNSUPPORTED(".word 0xe0ff1392 @ smlals pc, r1, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0f0f392 @ smlals r0, pc, r2, r3")
+       TEST_UNSUPPORTED(".word 0xe0f0139f @ smlals r0, r1, pc, r3")
+       TEST_UNSUPPORTED(".word 0xe0f01f92 @ smlals r0, r1, r2, pc")
+
+       TEST_GROUP("Synchronization primitives")
+
+       /*
+        * Use hard coded constants for SWP instructions to avoid warnings
+        * about deprecated instructions.
+        */
+       TEST_RP( ".word 0xe108e097 @ swp        lr, r",7,VAL2,", [r",8,0,"]")
+       TEST_R(  ".word 0x610d0091 @ swpvs      r0, r",1,VAL1,", [sp]")
+       TEST_RP( ".word 0xe10cd09e @ swp        sp, r",14,VAL2,", [r",12,13*4,"]")
+       TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]")
+       TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]")
+       TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]")
+       TEST_RP( ".word 0xe148e097 @ swpb       lr, r",7,VAL2,", [r",8,0,"]")
+       TEST_R(  ".word 0x614d0091 @ swpvsb     r0, r",1,VAL1,", [sp]")
+       TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]")
+
+       TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe1200090") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe1300090") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe1500090") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe1600090") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_UNSUPPORTED("ldrex r2, [sp]")
+       TEST_UNSUPPORTED("strexd        r0, r2, r3, [sp]")
+       TEST_UNSUPPORTED("ldrexd        r2, r3, [sp]")
+       TEST_UNSUPPORTED("strexb        r0, r2, [sp]")
+       TEST_UNSUPPORTED("ldrexb        r2, [sp]")
+       TEST_UNSUPPORTED("strexh        r0, r2, [sp]")
+       TEST_UNSUPPORTED("ldrexh        r2, [sp]")
+#endif
+       TEST_GROUP("Extra load/store instructions")
+
+       TEST_RPR(  "strh        r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")
+       TEST_RPR(  "streqh      r",14,VAL2,", [r",13,0, ", r",12, 48,"]")
+       TEST_RPR(  "strh        r",1, VAL1,", [r",2, 24,", r",3,  48,"]!")
+       TEST_RPR(  "strneh      r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+       TEST_RPR(  "strh        r",2, VAL1,", [r",3, 24,"], r",4, 48,"")
+       TEST_RPR(  "strh        r",10,VAL2,", [r",9, 48,"], -r",11,24,"")
+       TEST_UNSUPPORTED(".word 0xe1afc0ba      @ strh r12, [pc, r10]!")
+       TEST_UNSUPPORTED(".word 0xe089f0bb      @ strh pc, [r9], r11")
+       TEST_UNSUPPORTED(".word 0xe089a0bf      @ strh r10, [r9], pc")
+
+       TEST_PR(   "ldrh        r0, [r",0,  48,", -r",2, 24,"]")
+       TEST_PR(   "ldrcsh      r14, [r",13,0, ", r",12, 48,"]")
+       TEST_PR(   "ldrh        r1, [r",2,  24,", r",3,  48,"]!")
+       TEST_PR(   "ldrcch      r12, [r",11,48,", -r",10,24,"]!")
+       TEST_PR(   "ldrh        r2, [r",3,  24,"], r",4, 48,"")
+       TEST_PR(   "ldrh        r10, [r",9, 48,"], -r",11,24,"")
+       TEST_UNSUPPORTED(".word 0xe1bfc0ba      @ ldrh r12, [pc, r10]!")
+       TEST_UNSUPPORTED(".word 0xe099f0bb      @ ldrh pc, [r9], r11")
+       TEST_UNSUPPORTED(".word 0xe099a0bf      @ ldrh r10, [r9], pc")
+
+       TEST_RP(   "strh        r",0, VAL1,", [r",1, 24,", #-2]")
+       TEST_RP(   "strmih      r",14,VAL2,", [r",13,0, ", #2]")
+       TEST_RP(   "strh        r",1, VAL1,", [r",2, 24,", #4]!")
+       TEST_RP(   "strplh      r",12,VAL2,", [r",11,24,", #-4]!")
+       TEST_RP(   "strh        r",2, VAL1,", [r",3, 24,"], #48")
+       TEST_RP(   "strh        r",10,VAL2,", [r",9, 64,"], #-48")
+       TEST_UNSUPPORTED(".word 0xe1efc3b0      @ strh r12, [pc, #48]!")
+       TEST_UNSUPPORTED(".word 0xe0c9f3b0      @ strh pc, [r9], #48")
+
+       TEST_P(    "ldrh        r0, [r",0,  24,", #-2]")
+       TEST_P(    "ldrvsh      r14, [r",13,0, ", #2]")
+       TEST_P(    "ldrh        r1, [r",2,  24,", #4]!")
+       TEST_P(    "ldrvch      r12, [r",11,24,", #-4]!")
+       TEST_P(    "ldrh        r2, [r",3,  24,"], #48")
+       TEST_P(    "ldrh        r10, [r",9, 64,"], #-48")
+       TEST(      "ldrh        r0, [pc, #0]")
+       TEST_UNSUPPORTED(".word 0xe1ffc3b0      @ ldrh r12, [pc, #48]!")
+       TEST_UNSUPPORTED(".word 0xe0d9f3b0      @ ldrh pc, [r9], #48")
+
+       TEST_PR(   "ldrsb       r0, [r",0,  48,", -r",2, 24,"]")
+       TEST_PR(   "ldrhisb     r14, [r",13,0,", r",12,  48,"]")
+       TEST_PR(   "ldrsb       r1, [r",2,  24,", r",3,  48,"]!")
+       TEST_PR(   "ldrlssb     r12, [r",11,48,", -r",10,24,"]!")
+       TEST_PR(   "ldrsb       r2, [r",3,  24,"], r",4, 48,"")
+       TEST_PR(   "ldrsb       r10, [r",9, 48,"], -r",11,24,"")
+       TEST_UNSUPPORTED(".word 0xe1bfc0da      @ ldrsb r12, [pc, r10]!")
+       TEST_UNSUPPORTED(".word 0xe099f0db      @ ldrsb pc, [r9], r11")
+
+       TEST_P(    "ldrsb       r0, [r",0,  24,", #-1]")
+       TEST_P(    "ldrgesb     r14, [r",13,0, ", #1]")
+       TEST_P(    "ldrsb       r1, [r",2,  24,", #4]!")
+       TEST_P(    "ldrltsb     r12, [r",11,24,", #-4]!")
+       TEST_P(    "ldrsb       r2, [r",3,  24,"], #48")
+       TEST_P(    "ldrsb       r10, [r",9, 64,"], #-48")
+       TEST(      "ldrsb       r0, [pc, #0]")
+       TEST_UNSUPPORTED(".word 0xe1ffc3d0      @ ldrsb r12, [pc, #48]!")
+       TEST_UNSUPPORTED(".word 0xe0d9f3d0      @ ldrsb pc, [r9], #48")
+
+       TEST_PR(   "ldrsh       r0, [r",0,  48,", -r",2, 24,"]")
+       TEST_PR(   "ldrgtsh     r14, [r",13,0, ", r",12, 48,"]")
+       TEST_PR(   "ldrsh       r1, [r",2,  24,", r",3,  48,"]!")
+       TEST_PR(   "ldrlesh     r12, [r",11,48,", -r",10,24,"]!")
+       TEST_PR(   "ldrsh       r2, [r",3,  24,"], r",4, 48,"")
+       TEST_PR(   "ldrsh       r10, [r",9, 48,"], -r",11,24,"")
+       TEST_UNSUPPORTED(".word 0xe1bfc0fa      @ ldrsh r12, [pc, r10]!")
+       TEST_UNSUPPORTED(".word 0xe099f0fb      @ ldrsh pc, [r9], r11")
+
+       TEST_P(    "ldrsh       r0, [r",0,  24,", #-1]")
+       TEST_P(    "ldreqsh     r14, [r",13,0 ,", #1]")
+       TEST_P(    "ldrsh       r1, [r",2,  24,", #4]!")
+       TEST_P(    "ldrnesh     r12, [r",11,24,", #-4]!")
+       TEST_P(    "ldrsh       r2, [r",3,  24,"], #48")
+       TEST_P(    "ldrsh       r10, [r",9, 64,"], #-48")
+       TEST(      "ldrsh       r0, [pc, #0]")
+       TEST_UNSUPPORTED(".word 0xe1ffc3f0      @ ldrsh r12, [pc, #48]!")
+       TEST_UNSUPPORTED(".word 0xe0d9f3f0      @ ldrsh pc, [r9], #48")
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST_UNSUPPORTED("strht r1, [r2], r3")
+       TEST_UNSUPPORTED("ldrht r1, [r2], r3")
+       TEST_UNSUPPORTED("strht r1, [r2], #48")
+       TEST_UNSUPPORTED("ldrht r1, [r2], #48")
+       TEST_UNSUPPORTED("ldrsbt        r1, [r2], r3")
+       TEST_UNSUPPORTED("ldrsbt        r1, [r2], #48")
+       TEST_UNSUPPORTED("ldrsht        r1, [r2], r3")
+       TEST_UNSUPPORTED("ldrsht        r1, [r2], #48")
+#endif
+
+       TEST_RPR(  "strd        r",0, VAL1,", [r",1, 48,", -r",2,24,"]")
+       TEST_RPR(  "strccd      r",8, VAL2,", [r",13,0, ", r",12,48,"]")
+       TEST_RPR(  "strd        r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
+       TEST_RPR(  "strcsd      r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+       TEST_RPR(  "strd        r",2, VAL1,", [r",3, 24,"], r",4,48,"")
+       TEST_RPR(  "strd        r",10,VAL2,", [r",9, 48,"], -r",7,24,"")
+       TEST_UNSUPPORTED(".word 0xe1afc0fa      @ strd r12, [pc, r10]!")
+
+       TEST_PR(   "ldrd        r0, [r",0, 48,", -r",2,24,"]")
+       TEST_PR(   "ldrmid      r8, [r",13,0, ", r",12,48,"]")
+       TEST_PR(   "ldrd        r4, [r",2, 24,", r",3, 48,"]!")
+       TEST_PR(   "ldrpld      r6, [r",11,48,", -r",10,24,"]!")
+       TEST_PR(   "ldrd        r2, [r",5, 24,"], r",4,48,"")
+       TEST_PR(   "ldrd        r10, [r",9,48,"], -r",7,24,"")
+       TEST_UNSUPPORTED(".word 0xe1afc0da      @ ldrd r12, [pc, r10]!")
+       TEST_UNSUPPORTED(".word 0xe089f0db      @ ldrd pc, [r9], r11")
+       TEST_UNSUPPORTED(".word 0xe089e0db      @ ldrd lr, [r9], r11")
+       TEST_UNSUPPORTED(".word 0xe089c0df      @ ldrd r12, [r9], pc")
+
+       TEST_RP(   "strd        r",0, VAL1,", [r",1, 24,", #-8]")
+       TEST_RP(   "strvsd      r",8, VAL2,", [r",13,0, ", #8]")
+       TEST_RP(   "strd        r",4, VAL1,", [r",2, 24,", #16]!")
+       TEST_RP(   "strvcd      r",12,VAL2,", [r",11,24,", #-16]!")
+       TEST_RP(   "strd        r",2, VAL1,", [r",4, 24,"], #48")
+       TEST_RP(   "strd        r",10,VAL2,", [r",9, 64,"], #-48")
+       TEST_UNSUPPORTED(".word 0xe1efc3f0      @ strd r12, [pc, #48]!")
+
+       TEST_P(    "ldrd        r0, [r",0, 24,", #-8]")
+       TEST_P(    "ldrhid      r8, [r",13,0, ", #8]")
+       TEST_P(    "ldrd        r4, [r",2, 24,", #16]!")
+       TEST_P(    "ldrlsd      r6, [r",11,24,", #-16]!")
+       TEST_P(    "ldrd        r2, [r",5, 24,"], #48")
+       TEST_P(    "ldrd        r10, [r",9,6,"], #-48")
+       TEST_UNSUPPORTED(".word 0xe1efc3d0      @ ldrd r12, [pc, #48]!")
+       TEST_UNSUPPORTED(".word 0xe0c9f3d0      @ ldrd pc, [r9], #48")
+       TEST_UNSUPPORTED(".word 0xe0c9e3d0      @ ldrd lr, [r9], #48")
+
+       TEST_GROUP("Miscellaneous")
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST("movw      r0, #0")
+       TEST("movw      r0, #0xffff")
+       TEST("movw      lr, #0xffff")
+       TEST_UNSUPPORTED(".word 0xe300f000      @ movw pc, #0")
+       TEST_R("movt    r",0, VAL1,", #0")
+       TEST_R("movt    r",0, VAL2,", #0xffff")
+       TEST_R("movt    r",14,VAL1,", #0xffff")
+       TEST_UNSUPPORTED(".word 0xe340f000      @ movt pc, #0")
+#endif
+
+       TEST_UNSUPPORTED("msr   cpsr, 0x13")
+       TEST_UNSUPPORTED("msr   cpsr_f, 0xf0000000")
+       TEST_UNSUPPORTED("msr   spsr, 0x13")
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST_SUPPORTED("yield")
+       TEST("sev")
+       TEST("nop")
+       TEST("wfi")
+       TEST_SUPPORTED("wfe")
+       TEST_UNSUPPORTED("dbg #0")
+#endif
+
+       TEST_GROUP("Load/store word and unsigned byte")
+
+#define LOAD_STORE(byte)                                                       \
+       TEST_RP( "str"byte"     r",0, VAL1,", [r",1, 24,", #-2]")               \
+       TEST_RP( "str"byte"     r",14,VAL2,", [r",13,0, ", #2]")                \
+       TEST_RP( "str"byte"     r",1, VAL1,", [r",2, 24,", #4]!")               \
+       TEST_RP( "str"byte"     r",12,VAL2,", [r",11,24,", #-4]!")              \
+       TEST_RP( "str"byte"     r",2, VAL1,", [r",3, 24,"], #48")               \
+       TEST_RP( "str"byte"     r",10,VAL2,", [r",9, 64,"], #-48")              \
+       TEST_RPR("str"byte"     r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")       \
+       TEST_RPR("str"byte"     r",14,VAL2,", [r",13,0, ", r",12, 48,"]")       \
+       TEST_RPR("str"byte"     r",1, VAL1,", [r",2, 24,", r",3,  48,"]!")      \
+       TEST_RPR("str"byte"     r",12,VAL2,", [r",11,48,", -r",10,24,"]!")      \
+       TEST_RPR("str"byte"     r",2, VAL1,", [r",3, 24,"], r",4, 48,"")        \
+       TEST_RPR("str"byte"     r",10,VAL2,", [r",9, 48,"], -r",11,24,"")       \
+       TEST_RPR("str"byte"     r",0, VAL1,", [r",1, 24,", r",2,  32,", asl #1]")\
+       TEST_RPR("str"byte"     r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\
+       TEST_RPR("str"byte"     r",1, VAL1,", [r",2, 24,", r",3,  32,", asr #3]!")\
+       TEST_RPR("str"byte"     r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\
+       TEST_P(  "ldr"byte"     r0, [r",0,  24,", #-2]")                        \
+       TEST_P(  "ldr"byte"     r14, [r",13,0, ", #2]")                         \
+       TEST_P(  "ldr"byte"     r1, [r",2,  24,", #4]!")                        \
+       TEST_P(  "ldr"byte"     r12, [r",11,24,", #-4]!")                       \
+       TEST_P(  "ldr"byte"     r2, [r",3,  24,"], #48")                        \
+       TEST_P(  "ldr"byte"     r10, [r",9, 64,"], #-48")                       \
+       TEST_PR( "ldr"byte"     r0, [r",0,  48,", -r",2, 24,"]")                \
+       TEST_PR( "ldr"byte"     r14, [r",13,0, ", r",12, 48,"]")                \
+       TEST_PR( "ldr"byte"     r1, [r",2,  24,", r",3, 48,"]!")                \
+       TEST_PR( "ldr"byte"     r12, [r",11,48,", -r",10,24,"]!")               \
+       TEST_PR( "ldr"byte"     r2, [r",3,  24,"], r",4, 48,"")                 \
+       TEST_PR( "ldr"byte"     r10, [r",9, 48,"], -r",11,24,"")                \
+       TEST_PR( "ldr"byte"     r0, [r",0,  24,", r",2,  32,", asl #1]")        \
+       TEST_PR( "ldr"byte"     r14, [r",13,0, ", r",12, 32,", lsr #2]")        \
+       TEST_PR( "ldr"byte"     r1, [r",2,  24,", r",3,  32,", asr #3]!")       \
+       TEST_PR( "ldr"byte"     r12, [r",11,24,", r",10, 4,", ror #31]!")       \
+       TEST(    "ldr"byte"     r0, [pc, #0]")                                  \
+       TEST_R(  "ldr"byte"     r12, [pc, r",14,0,"]")
+
+       LOAD_STORE("")
+       TEST_P(   "str  pc, [r",0,0,", #15*4]")
+       TEST_R(   "str  pc, [sp, r",2,15*4,"]")
+       TEST_BF(  "ldr  pc, [sp, #15*4]")
+       TEST_BF_R("ldr  pc, [sp, r",2,15*4,"]")
+
+       TEST_P(   "str  sp, [r",0,0,", #13*4]")
+       TEST_R(   "str  sp, [sp, r",2,13*4,"]")
+       TEST_BF(  "ldr  sp, [sp, #13*4]")
+       TEST_BF_R("ldr  sp, [sp, r",2,13*4,"]")
+
+#ifdef CONFIG_THUMB2_KERNEL
+       TEST_ARM_TO_THUMB_INTERWORK_P("ldr      pc, [r",0,0,", #15*4]")
+#endif
+       TEST_UNSUPPORTED(".word 0xe5af6008      @ str r6, [pc, #8]!")
+       TEST_UNSUPPORTED(".word 0xe7af6008      @ str r6, [pc, r8]!")
+       TEST_UNSUPPORTED(".word 0xe5bf6008      @ ldr r6, [pc, #8]!")
+       TEST_UNSUPPORTED(".word 0xe7bf6008      @ ldr r6, [pc, r8]!")
+       TEST_UNSUPPORTED(".word 0xe788600f      @ str r6, [r8, pc]")
+       TEST_UNSUPPORTED(".word 0xe798600f      @ ldr r6, [r8, pc]")
+
+       LOAD_STORE("b")
+       TEST_UNSUPPORTED(".word 0xe5f7f008      @ ldrb pc, [r7, #8]!")
+       TEST_UNSUPPORTED(".word 0xe7f7f008      @ ldrb pc, [r7, r8]!")
+       TEST_UNSUPPORTED(".word 0xe5ef6008      @ strb r6, [pc, #8]!")
+       TEST_UNSUPPORTED(".word 0xe7ef6008      @ strb r6, [pc, r3]!")
+       TEST_UNSUPPORTED(".word 0xe5ff6008      @ ldrb r6, [pc, #8]!")
+       TEST_UNSUPPORTED(".word 0xe7ff6008      @ ldrb r6, [pc, r3]!")
+
+       TEST_UNSUPPORTED("ldrt  r0, [r1], #4")
+       TEST_UNSUPPORTED("ldrt  r1, [r2], r3")
+       TEST_UNSUPPORTED("strt  r2, [r3], #4")
+       TEST_UNSUPPORTED("strt  r3, [r4], r5")
+       TEST_UNSUPPORTED("ldrbt r4, [r5], #4")
+       TEST_UNSUPPORTED("ldrbt r5, [r6], r7")
+       TEST_UNSUPPORTED("strbt r6, [r7], #4")
+       TEST_UNSUPPORTED("strbt r7, [r8], r9")
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST_GROUP("Parallel addition and subtraction, signed")
+
+       TEST_UNSUPPORTED(".word 0xe6000010") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe60fffff") /* Unallocated space */
+
+       TEST_RR(    "sadd16     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sadd16     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe61cff1a      @ sadd16        pc, r12, r10")
+       TEST_RR(    "sasx       r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sasx       r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe61cff3a      @ sasx  pc, r12, r10")
+       TEST_RR(    "ssax       r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "ssax       r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe61cff5a      @ ssax  pc, r12, r10")
+       TEST_RR(    "ssub16     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "ssub16     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe61cff7a      @ ssub16        pc, r12, r10")
+       TEST_RR(    "sadd8      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sadd8      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe61cff9a      @ sadd8 pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe61000b0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe61fffbf") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe61000d0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe61fffdf") /* Unallocated space */
+       TEST_RR(    "ssub8      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "ssub8      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe61cfffa      @ ssub8 pc, r12, r10")
+
+       TEST_RR(    "qadd16     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "qadd16     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe62cff1a      @ qadd16        pc, r12, r10")
+       TEST_RR(    "qasx       r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "qasx       r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe62cff3a      @ qasx  pc, r12, r10")
+       TEST_RR(    "qsax       r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "qsax       r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe62cff5a      @ qsax  pc, r12, r10")
+       TEST_RR(    "qsub16     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "qsub16     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe62cff7a      @ qsub16        pc, r12, r10")
+       TEST_RR(    "qadd8      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "qadd8      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe62cff9a      @ qadd8 pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe62000b0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe62fffbf") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe62000d0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe62fffdf") /* Unallocated space */
+       TEST_RR(    "qsub8      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "qsub8      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe62cfffa      @ qsub8 pc, r12, r10")
+
+       TEST_RR(    "shadd16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "shadd16    r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe63cff1a      @ shadd16       pc, r12, r10")
+       TEST_RR(    "shasx      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "shasx      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe63cff3a      @ shasx pc, r12, r10")
+       TEST_RR(    "shsax      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "shsax      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe63cff5a      @ shsax pc, r12, r10")
+       TEST_RR(    "shsub16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "shsub16    r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe63cff7a      @ shsub16       pc, r12, r10")
+       TEST_RR(    "shadd8     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "shadd8     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe63cff9a      @ shadd8        pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe63000b0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe63fffbf") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe63000d0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe63fffdf") /* Unallocated space */
+       TEST_RR(    "shsub8     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "shsub8     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe63cfffa      @ shsub8        pc, r12, r10")
+
+       TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+       TEST_UNSUPPORTED(".word 0xe6400010") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe64fffff") /* Unallocated space */
+
+       TEST_RR(    "uadd16     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uadd16     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe65cff1a      @ uadd16        pc, r12, r10")
+       TEST_RR(    "uasx       r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uasx       r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe65cff3a      @ uasx  pc, r12, r10")
+       TEST_RR(    "usax       r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "usax       r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe65cff5a      @ usax  pc, r12, r10")
+       TEST_RR(    "usub16     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "usub16     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe65cff7a      @ usub16        pc, r12, r10")
+       TEST_RR(    "uadd8      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uadd8      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe65cff9a      @ uadd8 pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe65000b0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe65fffbf") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe65000d0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe65fffdf") /* Unallocated space */
+       TEST_RR(    "usub8      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "usub8      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe65cfffa      @ usub8 pc, r12, r10")
+
+       TEST_RR(    "uqadd16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uqadd16    r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe66cff1a      @ uqadd16       pc, r12, r10")
+       TEST_RR(    "uqasx      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uqasx      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe66cff3a      @ uqasx pc, r12, r10")
+       TEST_RR(    "uqsax      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uqsax      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe66cff5a      @ uqsax pc, r12, r10")
+       TEST_RR(    "uqsub16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uqsub16    r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe66cff7a      @ uqsub16       pc, r12, r10")
+       TEST_RR(    "uqadd8     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uqadd8     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe66cff9a      @ uqadd8        pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe66000b0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe66fffbf") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe66000d0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe66fffdf") /* Unallocated space */
+       TEST_RR(    "uqsub8     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uqsub8     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe66cfffa      @ uqsub8        pc, r12, r10")
+
+       TEST_RR(    "uhadd16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uhadd16    r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe67cff1a      @ uhadd16       pc, r12, r10")
+       TEST_RR(    "uhasx      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uhasx      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe67cff3a      @ uhasx pc, r12, r10")
+       TEST_RR(    "uhsax      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uhsax      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe67cff5a      @ uhsax pc, r12, r10")
+       TEST_RR(    "uhsub16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uhsub16    r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe67cff7a      @ uhsub16       pc, r12, r10")
+       TEST_RR(    "uhadd8     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uhadd8     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe67cff9a      @ uhadd8        pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe67000b0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe67fffbf") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe67000d0") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe67fffdf") /* Unallocated space */
+       TEST_RR(    "uhsub8     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uhsub8     r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe67cfffa      @ uhsub8        pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe67feffa      @ uhsub8        r14, pc, r10")
+       TEST_UNSUPPORTED(".word 0xe67cefff      @ uhsub8        r14, r12, pc")
+#endif /* __LINUX_ARM_ARCH__ >= 7 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_GROUP("Packing, unpacking, saturation, and reversal")
+
+       TEST_RR(    "pkhbt      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "pkhbt      r14,r",12, HH1,", r",10,HH2,", lsl #2")
+       TEST_UNSUPPORTED(".word 0xe68cf11a      @ pkhbt pc, r12, r10, lsl #2")
+       TEST_RR(    "pkhtb      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "pkhtb      r14,r",12, HH1,", r",10,HH2,", asr #2")
+       TEST_UNSUPPORTED(".word 0xe68cf15a      @ pkhtb pc, r12, r10, asr #2")
+       TEST_UNSUPPORTED(".word 0xe68fe15a      @ pkhtb r14, pc, r10, asr #2")
+       TEST_UNSUPPORTED(".word 0xe68ce15f      @ pkhtb r14, r12, pc, asr #2")
+       TEST_UNSUPPORTED(".word 0xe6900010") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe69fffdf") /* Unallocated space */
+
+       TEST_R(     "ssat       r0, #24, r",0,   VAL1,"")
+       TEST_R(     "ssat       r14, #24, r",12, VAL2,"")
+       TEST_R(     "ssat       r0, #24, r",0,   VAL1,", lsl #8")
+       TEST_R(     "ssat       r14, #24, r",12, VAL2,", asr #8")
+       TEST_UNSUPPORTED(".word 0xe6b7f01c      @ ssat  pc, #24, r12")
+
+       TEST_R(     "usat       r0, #24, r",0,   VAL1,"")
+       TEST_R(     "usat       r14, #24, r",12, VAL2,"")
+       TEST_R(     "usat       r0, #24, r",0,   VAL1,", lsl #8")
+       TEST_R(     "usat       r14, #24, r",12, VAL2,", asr #8")
+       TEST_UNSUPPORTED(".word 0xe6f7f01c      @ usat  pc, #24, r12")
+
+       TEST_RR(    "sxtab16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sxtab16    r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "sxtb16     r8, r",7,  HH1,"")
+       TEST_UNSUPPORTED(".word 0xe68cf47a      @ sxtab16       pc,r12, r10, ror #8")
+
+       TEST_RR(    "sel        r0, r",0,  VAL1,", r",1, VAL2,"")
+       TEST_RR(    "sel        r14, r",12,VAL1,", r",10, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe68cffba      @ sel   pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe68fefba      @ sel   r14, pc, r10")
+       TEST_UNSUPPORTED(".word 0xe68cefbf      @ sel   r14, r12, pc")
+
+       TEST_R(     "ssat16     r0, #12, r",0,   HH1,"")
+       TEST_R(     "ssat16     r14, #12, r",12, HH2,"")
+       TEST_UNSUPPORTED(".word 0xe6abff3c      @ ssat16        pc, #12, r12")
+
+       TEST_RR(    "sxtab      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sxtab      r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "sxtb       r8, r",7,  HH1,"")
+       TEST_UNSUPPORTED(".word 0xe6acf47a      @ sxtab pc,r12, r10, ror #8")
+
+       TEST_R(     "rev        r0, r",0,   VAL1,"")
+       TEST_R(     "rev        r14, r",12, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe6bfff3c      @ rev   pc, r12")
+
+       TEST_RR(    "sxtah      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sxtah      r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "sxth       r8, r",7,  HH1,"")
+       TEST_UNSUPPORTED(".word 0xe6bcf47a      @ sxtah pc,r12, r10, ror #8")
+
+       TEST_R(     "rev16      r0, r",0,   VAL1,"")
+       TEST_R(     "rev16      r14, r",12, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe6bfffbc      @ rev16 pc, r12")
+
+       TEST_RR(    "uxtab16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uxtab16    r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "uxtb16     r8, r",7,  HH1,"")
+       TEST_UNSUPPORTED(".word 0xe6ccf47a      @ uxtab16       pc,r12, r10, ror #8")
+
+       TEST_R(     "usat16     r0, #12, r",0,   HH1,"")
+       TEST_R(     "usat16     r14, #12, r",12, HH2,"")
+       TEST_UNSUPPORTED(".word 0xe6ecff3c      @ usat16        pc, #12, r12")
+       TEST_UNSUPPORTED(".word 0xe6ecef3f      @ usat16        r14, #12, pc")
+
+       TEST_RR(    "uxtab      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uxtab      r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "uxtb       r8, r",7,  HH1,"")
+       TEST_UNSUPPORTED(".word 0xe6ecf47a      @ uxtab pc,r12, r10, ror #8")
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST_R(     "rbit       r0, r",0,   VAL1,"")
+       TEST_R(     "rbit       r14, r",12, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe6ffff3c      @ rbit  pc, r12")
+#endif
+
+       TEST_RR(    "uxtah      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uxtah      r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "uxth       r8, r",7,  HH1,"")
+       TEST_UNSUPPORTED(".word 0xe6fff077      @ uxth  pc, r7")
+       TEST_UNSUPPORTED(".word 0xe6ff807f      @ uxth  r8, pc")
+       TEST_UNSUPPORTED(".word 0xe6fcf47a      @ uxtah pc, r12, r10, ror #8")
+       TEST_UNSUPPORTED(".word 0xe6fce47f      @ uxtah r14, r12, pc, ror #8")
+
+       TEST_R(     "revsh      r0, r",0,   VAL1,"")
+       TEST_R(     "revsh      r14, r",12, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe6ffff3c      @ revsh pc, r12")
+       TEST_UNSUPPORTED(".word 0xe6ffef3f      @ revsh r14, pc")
+
+       TEST_UNSUPPORTED(".word 0xe6900070") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe69fff7f") /* Unallocated space */
+
+       TEST_UNSUPPORTED(".word 0xe6d00070") /* Unallocated space */
+       TEST_UNSUPPORTED(".word 0xe6dfff7f") /* Unallocated space */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_GROUP("Signed multiplies")
+
+       TEST_RRR(   "smlad      r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+       TEST_RRR(   "smlad      r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe70f8a1c      @ smlad pc, r12, r10, r8")
+       TEST_RRR(   "smladx     r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+       TEST_RRR(   "smladx     r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe70f8a3c      @ smladx        pc, r12, r10, r8")
+
+       TEST_RR(   "smuad       r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(   "smuad       r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe70ffa1c      @ smuad pc, r12, r10")
+       TEST_RR(   "smuadx      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(   "smuadx      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe70ffa3c      @ smuadx        pc, r12, r10")
+
+       TEST_RRR(   "smlsd      r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+       TEST_RRR(   "smlsd      r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe70f8a5c      @ smlsd pc, r12, r10, r8")
+       TEST_RRR(   "smlsdx     r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+       TEST_RRR(   "smlsdx     r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe70f8a7c      @ smlsdx        pc, r12, r10, r8")
+
+       TEST_RR(   "smusd       r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(   "smusd       r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe70ffa5c      @ smusd pc, r12, r10")
+       TEST_RR(   "smusdx      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(   "smusdx      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_UNSUPPORTED(".word 0xe70ffa7c      @ smusdx        pc, r12, r10")
+
+       TEST_RRRR( "smlald      r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+       TEST_RRRR( "smlald      r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+       TEST_UNSUPPORTED(".word 0xe74af819      @ smlald        pc, r10, r9, r8")
+       TEST_UNSUPPORTED(".word 0xe74fb819      @ smlald        r11, pc, r9, r8")
+       TEST_UNSUPPORTED(".word 0xe74ab81f      @ smlald        r11, r10, pc, r8")
+       TEST_UNSUPPORTED(".word 0xe74abf19      @ smlald        r11, r10, r9, pc")
+
+       TEST_RRRR( "smlaldx     r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+       TEST_RRRR( "smlaldx     r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+       TEST_UNSUPPORTED(".word 0xe74af839      @ smlaldx       pc, r10, r9, r8")
+       TEST_UNSUPPORTED(".word 0xe74fb839      @ smlaldx       r11, pc, r9, r8")
+
+       TEST_RRR(  "smmla       r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+       TEST_RRR(  "smmla       r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe75f8a1c      @ smmla pc, r12, r10, r8")
+       TEST_RRR(  "smmlar      r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+       TEST_RRR(  "smmlar      r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe75f8a3c      @ smmlar        pc, r12, r10, r8")
+
+       TEST_RR(   "smmul       r0, r",0,  VAL1,", r",1, VAL2,"")
+       TEST_RR(   "smmul       r14, r",12,VAL2,", r",10,VAL1,"")
+       TEST_UNSUPPORTED(".word 0xe75ffa1c      @ smmul pc, r12, r10")
+       TEST_RR(   "smmulr      r0, r",0,  VAL1,", r",1, VAL2,"")
+       TEST_RR(   "smmulr      r14, r",12,VAL2,", r",10,VAL1,"")
+       TEST_UNSUPPORTED(".word 0xe75ffa3c      @ smmulr        pc, r12, r10")
+
+       TEST_RRR(  "smmls       r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+       TEST_RRR(  "smmls       r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe75f8adc      @ smmls pc, r12, r10, r8")
+       TEST_RRR(  "smmlsr      r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+       TEST_RRR(  "smmlsr      r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+       TEST_UNSUPPORTED(".word 0xe75f8afc      @ smmlsr        pc, r12, r10, r8")
+       TEST_UNSUPPORTED(".word 0xe75e8aff      @ smmlsr        r14, pc, r10, r8")
+       TEST_UNSUPPORTED(".word 0xe75e8ffc      @ smmlsr        r14, r12, pc, r8")
+       TEST_UNSUPPORTED(".word 0xe75efafc      @ smmlsr        r14, r12, r10, pc")
+
+       TEST_RR(   "usad8       r0, r",0,  VAL1,", r",1, VAL2,"")
+       TEST_RR(   "usad8       r14, r",12,VAL2,", r",10,VAL1,"")
+       TEST_UNSUPPORTED(".word 0xe75ffa1c      @ usad8 pc, r12, r10")
+       TEST_UNSUPPORTED(".word 0xe75efa1f      @ usad8 r14, pc, r10")
+       TEST_UNSUPPORTED(".word 0xe75eff1c      @ usad8 r14, r12, pc")
+
+       TEST_RRR(  "usada8      r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL3,"")
+       TEST_RRR(  "usada8      r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+       TEST_UNSUPPORTED(".word 0xe78f8a1c      @ usada8        pc, r12, r10, r8")
+       TEST_UNSUPPORTED(".word 0xe78e8a1f      @ usada8        r14, pc, r10, r8")
+       TEST_UNSUPPORTED(".word 0xe78e8f1c      @ usada8        r14, r12, pc, r8")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST_GROUP("Bit Field")
+
+       TEST_R(     "sbfx       r0, r",0  , VAL1,", #0, #31")
+       TEST_R(     "sbfxeq     r14, r",12, VAL2,", #8, #16")
+       TEST_R(     "sbfx       r4, r",10,  VAL1,", #16, #15")
+       TEST_UNSUPPORTED(".word 0xe7aff45c      @ sbfx  pc, r12, #8, #16")
+
+       TEST_R(     "ubfx       r0, r",0  , VAL1,", #0, #31")
+       TEST_R(     "ubfxcs     r14, r",12, VAL2,", #8, #16")
+       TEST_R(     "ubfx       r4, r",10,  VAL1,", #16, #15")
+       TEST_UNSUPPORTED(".word 0xe7eff45c      @ ubfx  pc, r12, #8, #16")
+       TEST_UNSUPPORTED(".word 0xe7efc45f      @ ubfx  r12, pc, #8, #16")
+
+       TEST_R(     "bfc        r",0, VAL1,", #4, #20")
+       TEST_R(     "bfcvs      r",14,VAL2,", #4, #20")
+       TEST_R(     "bfc        r",7, VAL1,", #0, #31")
+       TEST_R(     "bfc        r",8, VAL2,", #0, #31")
+       TEST_UNSUPPORTED(".word 0xe7def01f      @ bfc   pc, #0, #31");
+
+       TEST_RR(    "bfi        r",0, VAL1,", r",0  , VAL2,", #0, #31")
+       TEST_RR(    "bfipl      r",12,VAL1,", r",14 , VAL2,", #4, #20")
+       TEST_UNSUPPORTED(".word 0xe7d7f21e      @ bfi   pc, r14, #4, #20")
+
+       TEST_UNSUPPORTED(".word 0x07f000f0")  /* Permanently UNDEFINED */
+       TEST_UNSUPPORTED(".word 0x07ffffff")  /* Permanently UNDEFINED */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+       TEST_GROUP("Branch, branch with link, and block data transfer")
+
+       TEST_P(   "stmda        r",0, 16*4,", {r0}")
+       TEST_P(   "stmeqda      r",4, 16*4,", {r0-r15}")
+       TEST_P(   "stmneda      r",8, 16*4,"!, {r8-r15}")
+       TEST_P(   "stmda        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_P(   "stmda        r",13,0,   "!, {pc}")
+
+       TEST_P(   "ldmda        r",0, 16*4,", {r0}")
+       TEST_BF_P("ldmcsda      r",4, 15*4,", {r0-r15}")
+       TEST_BF_P("ldmccda      r",7, 15*4,"!, {r8-r15}")
+       TEST_P(   "ldmda        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_BF_P("ldmda        r",14,15*4,"!, {pc}")
+
+       TEST_P(   "stmia        r",0, 16*4,", {r0}")
+       TEST_P(   "stmmiia      r",4, 16*4,", {r0-r15}")
+       TEST_P(   "stmplia      r",8, 16*4,"!, {r8-r15}")
+       TEST_P(   "stmia        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_P(   "stmia        r",14,0,   "!, {pc}")
+
+       TEST_P(   "ldmia        r",0, 16*4,", {r0}")
+       TEST_BF_P("ldmvsia      r",4, 0,   ", {r0-r15}")
+       TEST_BF_P("ldmvcia      r",7, 8*4, "!, {r8-r15}")
+       TEST_P(   "ldmia        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_BF_P("ldmia        r",14,15*4,"!, {pc}")
+
+       TEST_P(   "stmdb        r",0, 16*4,", {r0}")
+       TEST_P(   "stmhidb      r",4, 16*4,", {r0-r15}")
+       TEST_P(   "stmlsdb      r",8, 16*4,"!, {r8-r15}")
+       TEST_P(   "stmdb        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_P(   "stmdb        r",13,4,   "!, {pc}")
+
+       TEST_P(   "ldmdb        r",0, 16*4,", {r0}")
+       TEST_BF_P("ldmgedb      r",4, 16*4,", {r0-r15}")
+       TEST_BF_P("ldmltdb      r",7, 16*4,"!, {r8-r15}")
+       TEST_P(   "ldmdb        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_BF_P("ldmdb        r",14,16*4,"!, {pc}")
+
+       TEST_P(   "stmib        r",0, 16*4,", {r0}")
+       TEST_P(   "stmgtib      r",4, 16*4,", {r0-r15}")
+       TEST_P(   "stmleib      r",8, 16*4,"!, {r8-r15}")
+       TEST_P(   "stmib        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_P(   "stmib        r",13,-4,  "!, {pc}")
+
+       TEST_P(   "ldmib        r",0, 16*4,", {r0}")
+       TEST_BF_P("ldmeqib      r",4, -4,", {r0-r15}")
+       TEST_BF_P("ldmneib      r",7, 7*4,"!, {r8-r15}")
+       TEST_P(   "ldmib        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_BF_P("ldmib        r",14,14*4,"!, {pc}")
+
+       TEST_P(   "stmdb        r",13,16*4,"!, {r3-r12,lr}")
+       TEST_P(   "stmeqdb      r",13,16*4,"!, {r3-r12}")
+       TEST_P(   "stmnedb      r",2, 16*4,", {r3-r12,lr}")
+       TEST_P(   "stmdb        r",13,16*4,"!, {r2-r12,lr}")
+       TEST_P(   "stmdb        r",0, 16*4,", {r0-r12}")
+       TEST_P(   "stmdb        r",0, 16*4,", {r0-r12,lr}")
+
+       TEST_BF_P("ldmia        r",13,5*4, "!, {r3-r12,pc}")
+       TEST_P(   "ldmccia      r",13,5*4, "!, {r3-r12}")
+       TEST_BF_P("ldmcsia      r",2, 5*4, "!, {r3-r12,pc}")
+       TEST_BF_P("ldmia        r",13,4*4, "!, {r2-r12,pc}")
+       TEST_P(   "ldmia        r",0, 16*4,", {r0-r12}")
+       TEST_P(   "ldmia        r",0, 16*4,", {r0-r12,lr}")
+
+#ifdef CONFIG_THUMB2_KERNEL
+       TEST_ARM_TO_THUMB_INTERWORK_P("ldmplia  r",0,15*4,", {pc}")
+       TEST_ARM_TO_THUMB_INTERWORK_P("ldmmiia  r",13,0,", {r0-r15}")
+#endif
+       TEST_BF("b      2f")
+       TEST_BF("bl     2f")
+       TEST_BB("b      2b")
+       TEST_BB("bl     2b")
+
+       TEST_BF("beq    2f")
+       TEST_BF("bleq   2f")
+       TEST_BB("bne    2b")
+       TEST_BB("blne   2b")
+
+       TEST_BF("bgt    2f")
+       TEST_BF("blgt   2f")
+       TEST_BB("blt    2b")
+       TEST_BB("bllt   2b")
+
+       TEST_GROUP("Supervisor Call, and coprocessor instructions")
+
+       /*
+        * We can't really test these by executing them, so all
+        * we can do is check that probes are, or are not allowed.
+        * At the moment none are allowed...
+        */
+#define TEST_COPROCESSOR(code) TEST_UNSUPPORTED(code)
+
+#define COPROCESSOR_INSTRUCTIONS_ST_LD(two,cc)                                 \
+       TEST_COPROCESSOR("stc"two"      0, cr0, [r13, #4]")                     \
+       TEST_COPROCESSOR("stc"two"      0, cr0, [r13, #-4]")                    \
+       TEST_COPROCESSOR("stc"two"      0, cr0, [r13, #4]!")                    \
+       TEST_COPROCESSOR("stc"two"      0, cr0, [r13, #-4]!")                   \
+       TEST_COPROCESSOR("stc"two"      0, cr0, [r13], #4")                     \
+       TEST_COPROCESSOR("stc"two"      0, cr0, [r13], #-4")                    \
+       TEST_COPROCESSOR("stc"two"      0, cr0, [r13], {1}")                    \
+       TEST_COPROCESSOR("stc"two"l     0, cr0, [r13, #4]")                     \
+       TEST_COPROCESSOR("stc"two"l     0, cr0, [r13, #-4]")                    \
+       TEST_COPROCESSOR("stc"two"l     0, cr0, [r13, #4]!")                    \
+       TEST_COPROCESSOR("stc"two"l     0, cr0, [r13, #-4]!")                   \
+       TEST_COPROCESSOR("stc"two"l     0, cr0, [r13], #4")                     \
+       TEST_COPROCESSOR("stc"two"l     0, cr0, [r13], #-4")                    \
+       TEST_COPROCESSOR("stc"two"l     0, cr0, [r13], {1}")                    \
+       TEST_COPROCESSOR("ldc"two"      0, cr0, [r13, #4]")                     \
+       TEST_COPROCESSOR("ldc"two"      0, cr0, [r13, #-4]")                    \
+       TEST_COPROCESSOR("ldc"two"      0, cr0, [r13, #4]!")                    \
+       TEST_COPROCESSOR("ldc"two"      0, cr0, [r13, #-4]!")                   \
+       TEST_COPROCESSOR("ldc"two"      0, cr0, [r13], #4")                     \
+       TEST_COPROCESSOR("ldc"two"      0, cr0, [r13], #-4")                    \
+       TEST_COPROCESSOR("ldc"two"      0, cr0, [r13], {1}")                    \
+       TEST_COPROCESSOR("ldc"two"l     0, cr0, [r13, #4]")                     \
+       TEST_COPROCESSOR("ldc"two"l     0, cr0, [r13, #-4]")                    \
+       TEST_COPROCESSOR("ldc"two"l     0, cr0, [r13, #4]!")                    \
+       TEST_COPROCESSOR("ldc"two"l     0, cr0, [r13, #-4]!")                   \
+       TEST_COPROCESSOR("ldc"two"l     0, cr0, [r13], #4")                     \
+       TEST_COPROCESSOR("ldc"two"l     0, cr0, [r13], #-4")                    \
+       TEST_COPROCESSOR("ldc"two"l     0, cr0, [r13], {1}")                    \
+                                                                               \
+       TEST_COPROCESSOR( "stc"two"     0, cr0, [r15, #4]")                     \
+       TEST_COPROCESSOR( "stc"two"     0, cr0, [r15, #-4]")                    \
+       TEST_UNSUPPORTED(".word 0x"cc"daf0001   @ stc"two"      0, cr0, [r15, #4]!")    \
+       TEST_UNSUPPORTED(".word 0x"cc"d2f0001   @ stc"two"      0, cr0, [r15, #-4]!")   \
+       TEST_UNSUPPORTED(".word 0x"cc"caf0001   @ stc"two"      0, cr0, [r15], #4")     \
+       TEST_UNSUPPORTED(".word 0x"cc"c2f0001   @ stc"two"      0, cr0, [r15], #-4")    \
+       TEST_COPROCESSOR( "stc"two"     0, cr0, [r15], {1}")                    \
+       TEST_COPROCESSOR( "stc"two"l    0, cr0, [r15, #4]")                     \
+       TEST_COPROCESSOR( "stc"two"l    0, cr0, [r15, #-4]")                    \
+       TEST_UNSUPPORTED(".word 0x"cc"def0001   @ stc"two"l     0, cr0, [r15, #4]!")    \
+       TEST_UNSUPPORTED(".word 0x"cc"d6f0001   @ stc"two"l     0, cr0, [r15, #-4]!")   \
+       TEST_UNSUPPORTED(".word 0x"cc"cef0001   @ stc"two"l     0, cr0, [r15], #4")     \
+       TEST_UNSUPPORTED(".word 0x"cc"c6f0001   @ stc"two"l     0, cr0, [r15], #-4")    \
+       TEST_COPROCESSOR( "stc"two"l    0, cr0, [r15], {1}")                    \
+       TEST_COPROCESSOR( "ldc"two"     0, cr0, [r15, #4]")                     \
+       TEST_COPROCESSOR( "ldc"two"     0, cr0, [r15, #-4]")                    \
+       TEST_UNSUPPORTED(".word 0x"cc"dbf0001   @ ldc"two"      0, cr0, [r15, #4]!")    \
+       TEST_UNSUPPORTED(".word 0x"cc"d3f0001   @ ldc"two"      0, cr0, [r15, #-4]!")   \
+       TEST_UNSUPPORTED(".word 0x"cc"cbf0001   @ ldc"two"      0, cr0, [r15], #4")     \
+       TEST_UNSUPPORTED(".word 0x"cc"c3f0001   @ ldc"two"      0, cr0, [r15], #-4")    \
+       TEST_COPROCESSOR( "ldc"two"     0, cr0, [r15], {1}")                    \
+       TEST_COPROCESSOR( "ldc"two"l    0, cr0, [r15, #4]")                     \
+       TEST_COPROCESSOR( "ldc"two"l    0, cr0, [r15, #-4]")                    \
+       TEST_UNSUPPORTED(".word 0x"cc"dff0001   @ ldc"two"l     0, cr0, [r15, #4]!")    \
+       TEST_UNSUPPORTED(".word 0x"cc"d7f0001   @ ldc"two"l     0, cr0, [r15, #-4]!")   \
+       TEST_UNSUPPORTED(".word 0x"cc"cff0001   @ ldc"two"l     0, cr0, [r15], #4")     \
+       TEST_UNSUPPORTED(".word 0x"cc"c7f0001   @ ldc"two"l     0, cr0, [r15], #-4")    \
+       TEST_COPROCESSOR( "ldc"two"l    0, cr0, [r15], {1}")
+
+#define COPROCESSOR_INSTRUCTIONS_MC_MR(two,cc)                                 \
+                                                                               \
+       TEST_COPROCESSOR( "mcrr"two"    0, 15, r0, r14, cr0")                   \
+       TEST_COPROCESSOR( "mcrr"two"    15, 0, r14, r0, cr15")                  \
+       TEST_UNSUPPORTED(".word 0x"cc"c4f00f0   @ mcrr"two"     0, 15, r0, r15, cr0")   \
+       TEST_UNSUPPORTED(".word 0x"cc"c40ff0f   @ mcrr"two"     15, 0, r15, r0, cr15")  \
+       TEST_COPROCESSOR( "mrrc"two"    0, 15, r0, r14, cr0")                   \
+       TEST_COPROCESSOR( "mrrc"two"    15, 0, r14, r0, cr15")                  \
+       TEST_UNSUPPORTED(".word 0x"cc"c5f00f0   @ mrrc"two"     0, 15, r0, r15, cr0")   \
+       TEST_UNSUPPORTED(".word 0x"cc"c50ff0f   @ mrrc"two"     15, 0, r15, r0, cr15")  \
+       TEST_COPROCESSOR( "cdp"two"     15, 15, cr15, cr15, cr15, 7")           \
+       TEST_COPROCESSOR( "cdp"two"     0, 0, cr0, cr0, cr0, 0")                \
+       TEST_COPROCESSOR( "mcr"two"     15, 7, r15, cr15, cr15, 7")             \
+       TEST_COPROCESSOR( "mcr"two"     0, 0, r0, cr0, cr0, 0")                 \
+       TEST_COPROCESSOR( "mrc"two"     15, 7, r15, cr15, cr15, 7")             \
+       TEST_COPROCESSOR( "mrc"two"     0, 0, r0, cr0, cr0, 0")
+
+       COPROCESSOR_INSTRUCTIONS_ST_LD("","e")
+       COPROCESSOR_INSTRUCTIONS_MC_MR("","e")
+       TEST_UNSUPPORTED("svc   0")
+       TEST_UNSUPPORTED("svc   0xffffff")
+
+       TEST_UNSUPPORTED("svc   0")
+
+       TEST_GROUP("Unconditional instruction")
+
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_UNSUPPORTED("srsda sp, 0x13")
+       TEST_UNSUPPORTED("srsdb sp, 0x13")
+       TEST_UNSUPPORTED("srsia sp, 0x13")
+       TEST_UNSUPPORTED("srsib sp, 0x13")
+       TEST_UNSUPPORTED("srsda sp!, 0x13")
+       TEST_UNSUPPORTED("srsdb sp!, 0x13")
+       TEST_UNSUPPORTED("srsia sp!, 0x13")
+       TEST_UNSUPPORTED("srsib sp!, 0x13")
+
+       TEST_UNSUPPORTED("rfeda sp")
+       TEST_UNSUPPORTED("rfedb sp")
+       TEST_UNSUPPORTED("rfeia sp")
+       TEST_UNSUPPORTED("rfeib sp")
+       TEST_UNSUPPORTED("rfeda sp!")
+       TEST_UNSUPPORTED("rfedb sp!")
+       TEST_UNSUPPORTED("rfeia sp!")
+       TEST_UNSUPPORTED("rfeib sp!")
+       TEST_UNSUPPORTED(".word 0xf81d0a00      @ rfeda pc")
+       TEST_UNSUPPORTED(".word 0xf91d0a00      @ rfedb pc")
+       TEST_UNSUPPORTED(".word 0xf89d0a00      @ rfeia pc")
+       TEST_UNSUPPORTED(".word 0xf99d0a00      @ rfeib pc")
+       TEST_UNSUPPORTED(".word 0xf83d0a00      @ rfeda pc!")
+       TEST_UNSUPPORTED(".word 0xf93d0a00      @ rfedb pc!")
+       TEST_UNSUPPORTED(".word 0xf8bd0a00      @ rfeia pc!")
+       TEST_UNSUPPORTED(".word 0xf9bd0a00      @ rfeib pc!")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_X( "blx    __dummy_thumb_subroutine_even",
+               ".thumb                         \n\t"
+               ".space 4                       \n\t"
+               ".type __dummy_thumb_subroutine_even, %%function \n\t"
+               "__dummy_thumb_subroutine_even: \n\t"
+               "mov    r0, pc                  \n\t"
+               "bx     lr                      \n\t"
+               ".arm                           \n\t"
+       )
+       TEST(   "blx    __dummy_thumb_subroutine_even")
+
+       TEST_X( "blx    __dummy_thumb_subroutine_odd",
+               ".thumb                         \n\t"
+               ".space 2                       \n\t"
+               ".type __dummy_thumb_subroutine_odd, %%function \n\t"
+               "__dummy_thumb_subroutine_odd:  \n\t"
+               "mov    r0, pc                  \n\t"
+               "bx     lr                      \n\t"
+               ".arm                           \n\t"
+       )
+       TEST(   "blx    __dummy_thumb_subroutine_odd")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+       COPROCESSOR_INSTRUCTIONS_ST_LD("2","f")
+#if __LINUX_ARM_ARCH__ >= 6
+       COPROCESSOR_INSTRUCTIONS_MC_MR("2","f")
+#endif
+
+       TEST_GROUP("Miscellaneous instructions, memory hints, and Advanced SIMD instructions")
+
+#if __LINUX_ARM_ARCH__ >= 6
+       TEST_UNSUPPORTED("cps   0x13")
+       TEST_UNSUPPORTED("cpsie i")
+       TEST_UNSUPPORTED("cpsid i")
+       TEST_UNSUPPORTED("cpsie i,0x13")
+       TEST_UNSUPPORTED("cpsid i,0x13")
+       TEST_UNSUPPORTED("setend        le")
+       TEST_UNSUPPORTED("setend        be")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST_P("pli     [r",0,0b,", #16]")
+       TEST(  "pli     [pc, #0]")
+       TEST_RR("pli    [r",12,0b,", r",0, 16,"]")
+       TEST_RR("pli    [r",0, 0b,", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 5
+       TEST_P("pld     [r",0,32,", #-16]")
+       TEST(  "pld     [pc, #0]")
+       TEST_PR("pld    [r",7, 24, ", r",0, 16,"]")
+       TEST_PR("pld    [r",8, 24, ", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST_SUPPORTED(  ".word 0xf590f000      @ pldw [r0, #0]")
+       TEST_SUPPORTED(  ".word 0xf797f000      @ pldw  [r7, r0]")
+       TEST_SUPPORTED(  ".word 0xf798f18c      @ pldw  [r8, r12, lsl #3]");
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+       TEST_UNSUPPORTED("clrex")
+       TEST_UNSUPPORTED("dsb")
+       TEST_UNSUPPORTED("dmb")
+       TEST_UNSUPPORTED("isb")
+#endif
+
+       verbose("\n");
+}
+
diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c
new file mode 100644 (file)
index 0000000..5e726c3
--- /dev/null
@@ -0,0 +1,1187 @@
+/*
+ * arch/arm/kernel/kprobes-test-thumb.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "16"
+
+#define DONT_TEST_IN_ITBLOCK(tests)                    \
+       kprobe_test_flags |= TEST_FLAG_NO_ITBLOCK;      \
+       tests                                           \
+       kprobe_test_flags &= ~TEST_FLAG_NO_ITBLOCK;
+
+#define CONDITION_INSTRUCTIONS(cc_pos, tests)          \
+       kprobe_test_cc_position = cc_pos;               \
+       DONT_TEST_IN_ITBLOCK(tests)                     \
+       kprobe_test_cc_position = 0;
+
+#define TEST_ITBLOCK(code)                             \
+       kprobe_test_flags |= TEST_FLAG_FULL_ITBLOCK;    \
+       TESTCASE_START(code)                            \
+       TEST_ARG_END("")                                \
+       "50:    nop                     \n\t"           \
+       "1:     "code"                  \n\t"           \
+       "       mov r1, #0x11           \n\t"           \
+       "       mov r2, #0x22           \n\t"           \
+       "       mov r3, #0x33           \n\t"           \
+       "2:     nop                     \n\t"           \
+       TESTCASE_END                                    \
+       kprobe_test_flags &= ~TEST_FLAG_FULL_ITBLOCK;
+
+#define TEST_THUMB_TO_ARM_INTERWORK_P(code1, reg, val, code2)  \
+       TESTCASE_START(code1 #reg code2)                        \
+       TEST_ARG_PTR(reg, val)                                  \
+       TEST_ARG_REG(14, 99f+1)                                 \
+       TEST_ARG_MEM(15, 3f)                                    \
+       TEST_ARG_END("")                                        \
+       "       nop                     \n\t" /* To align 1f */ \
+       "50:    nop                     \n\t"                   \
+       "1:     "code1 #reg code2"      \n\t"                   \
+       "       bx      lr              \n\t"                   \
+       ".arm                           \n\t"                   \
+       "3:     adr     lr, 2f+1        \n\t"                   \
+       "       bx      lr              \n\t"                   \
+       ".thumb                         \n\t"                   \
+       "2:     nop                     \n\t"                   \
+       TESTCASE_END
+
+
+void kprobe_thumb16_test_cases(void)
+{
+       kprobe_test_flags = TEST_FLAG_NARROW_INSTR;
+
+       TEST_GROUP("Shift (immediate), add, subtract, move, and compare")
+
+       TEST_R(    "lsls        r7, r",0,VAL1,", #5")
+       TEST_R(    "lsls        r0, r",7,VAL2,", #11")
+       TEST_R(    "lsrs        r7, r",0,VAL1,", #5")
+       TEST_R(    "lsrs        r0, r",7,VAL2,", #11")
+       TEST_R(    "asrs        r7, r",0,VAL1,", #5")
+       TEST_R(    "asrs        r0, r",7,VAL2,", #11")
+       TEST_RR(   "adds        r2, r",0,VAL1,", r",7,VAL2,"")
+       TEST_RR(   "adds        r5, r",7,VAL2,", r",0,VAL2,"")
+       TEST_RR(   "subs        r2, r",0,VAL1,", r",7,VAL2,"")
+       TEST_RR(   "subs        r5, r",7,VAL2,", r",0,VAL2,"")
+       TEST_R(    "adds        r7, r",0,VAL1,", #5")
+       TEST_R(    "adds        r0, r",7,VAL2,", #2")
+       TEST_R(    "subs        r7, r",0,VAL1,", #5")
+       TEST_R(    "subs        r0, r",7,VAL2,", #2")
+       TEST(      "movs.n      r0, #0x5f")
+       TEST(      "movs.n      r7, #0xa0")
+       TEST_R(    "cmp.n       r",0,0x5e, ", #0x5f")
+       TEST_R(    "cmp.n       r",5,0x15f,", #0x5f")
+       TEST_R(    "cmp.n       r",7,0xa0, ", #0xa0")
+       TEST_R(    "adds.n      r",0,VAL1,", #0x5f")
+       TEST_R(    "adds.n      r",7,VAL2,", #0xa0")
+       TEST_R(    "subs.n      r",0,VAL1,", #0x5f")
+       TEST_R(    "subs.n      r",7,VAL2,", #0xa0")
+
+       TEST_GROUP("16-bit Thumb data-processing instructions")
+
+#define DATA_PROCESSING16(op,val)                      \
+       TEST_RR(   op"  r",0,VAL1,", r",7,val,"")       \
+       TEST_RR(   op"  r",7,VAL2,", r",0,val,"")
+
+       DATA_PROCESSING16("ands",0xf00f00ff)
+       DATA_PROCESSING16("eors",0xf00f00ff)
+       DATA_PROCESSING16("lsls",11)
+       DATA_PROCESSING16("lsrs",11)
+       DATA_PROCESSING16("asrs",11)
+       DATA_PROCESSING16("adcs",VAL2)
+       DATA_PROCESSING16("sbcs",VAL2)
+       DATA_PROCESSING16("rors",11)
+       DATA_PROCESSING16("tst",0xf00f00ff)
+       TEST_R("rsbs    r",0,VAL1,", #0")
+       TEST_R("rsbs    r",7,VAL2,", #0")
+       DATA_PROCESSING16("cmp",0xf00f00ff)
+       DATA_PROCESSING16("cmn",0xf00f00ff)
+       DATA_PROCESSING16("orrs",0xf00f00ff)
+       DATA_PROCESSING16("muls",VAL2)
+       DATA_PROCESSING16("bics",0xf00f00ff)
+       DATA_PROCESSING16("mvns",VAL2)
+
+       TEST_GROUP("Special data instructions and branch and exchange")
+
+       TEST_RR(  "add  r",0, VAL1,", r",7,VAL2,"")
+       TEST_RR(  "add  r",3, VAL2,", r",8,VAL3,"")
+       TEST_RR(  "add  r",8, VAL3,", r",0,VAL1,"")
+       TEST_R(   "add  sp"        ", r",8,-8,  "")
+       TEST_R(   "add  r",14,VAL1,", pc")
+       TEST_BF_R("add  pc"        ", r",0,2f-1f-8,"")
+       TEST_UNSUPPORTED(".short 0x44ff @ add pc, pc")
+
+       TEST_RR(  "cmp  r",3,VAL1,", r",8,VAL2,"")
+       TEST_RR(  "cmp  r",8,VAL2,", r",0,VAL1,"")
+       TEST_R(   "cmp  sp"       ", r",8,-8,  "")
+
+       TEST_R(   "mov  r0, r",7,VAL2,"")
+       TEST_R(   "mov  r3, r",8,VAL3,"")
+       TEST_R(   "mov  r8, r",0,VAL1,"")
+       TEST_P(   "mov  sp, r",8,-8,  "")
+       TEST(     "mov  lr, pc")
+       TEST_BF_R("mov  pc, r",0,2f,  "")
+
+       TEST_BF_R("bx   r",0, 2f+1,"")
+       TEST_BF_R("bx   r",14,2f+1,"")
+       TESTCASE_START("bx      pc")
+               TEST_ARG_REG(14, 99f+1)
+               TEST_ARG_END("")
+               "       nop                     \n\t" /* To align the bx pc*/
+               "50:    nop                     \n\t"
+               "1:     bx      pc              \n\t"
+               "       bx      lr              \n\t"
+               ".arm                           \n\t"
+               "       adr     lr, 2f+1        \n\t"
+               "       bx      lr              \n\t"
+               ".thumb                         \n\t"
+               "2:     nop                     \n\t"
+       TESTCASE_END
+
+       TEST_BF_R("blx  r",0, 2f+1,"")
+       TEST_BB_R("blx  r",14,2f+1,"")
+       TEST_UNSUPPORTED(".short 0x47f8 @ blx pc")
+
+       TEST_GROUP("Load from Literal Pool")
+
+       TEST_X( "ldr    r0, 3f",
+               ".align                                 \n\t"
+               "3:     .word   "__stringify(VAL1))
+       TEST_X( "ldr    r7, 3f",
+               ".space 128                             \n\t"
+               ".align                                 \n\t"
+               "3:     .word   "__stringify(VAL2))
+
+       TEST_GROUP("16-bit Thumb Load/store instructions")
+
+       TEST_RPR("str   r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+       TEST_RPR("str   r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+       TEST_RPR("strh  r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+       TEST_RPR("strh  r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+       TEST_RPR("strb  r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+       TEST_RPR("strb  r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+       TEST_PR( "ldrsb r0, [r",1, 24,", r",2,  48,"]")
+       TEST_PR( "ldrsb r7, [r",6, 24,", r",5,  50,"]")
+       TEST_PR( "ldr   r0, [r",1, 24,", r",2,  48,"]")
+       TEST_PR( "ldr   r7, [r",6, 24,", r",5,  48,"]")
+       TEST_PR( "ldrh  r0, [r",1, 24,", r",2,  48,"]")
+       TEST_PR( "ldrh  r7, [r",6, 24,", r",5,  50,"]")
+       TEST_PR( "ldrb  r0, [r",1, 24,", r",2,  48,"]")
+       TEST_PR( "ldrb  r7, [r",6, 24,", r",5,  50,"]")
+       TEST_PR( "ldrsh r0, [r",1, 24,", r",2,  48,"]")
+       TEST_PR( "ldrsh r7, [r",6, 24,", r",5,  50,"]")
+
+       TEST_RP("str    r",0, VAL1,", [r",1, 24,", #120]")
+       TEST_RP("str    r",7, VAL2,", [r",6, 24,", #120]")
+       TEST_P( "ldr    r0, [r",1, 24,", #120]")
+       TEST_P( "ldr    r7, [r",6, 24,", #120]")
+       TEST_RP("strb   r",0, VAL1,", [r",1, 24,", #30]")
+       TEST_RP("strb   r",7, VAL2,", [r",6, 24,", #30]")
+       TEST_P( "ldrb   r0, [r",1, 24,", #30]")
+       TEST_P( "ldrb   r7, [r",6, 24,", #30]")
+       TEST_RP("strh   r",0, VAL1,", [r",1, 24,", #60]")
+       TEST_RP("strh   r",7, VAL2,", [r",6, 24,", #60]")
+       TEST_P( "ldrh   r0, [r",1, 24,", #60]")
+       TEST_P( "ldrh   r7, [r",6, 24,", #60]")
+
+       TEST_R( "str    r",0, VAL1,", [sp, #0]")
+       TEST_R( "str    r",7, VAL2,", [sp, #160]")
+       TEST(   "ldr    r0, [sp, #0]")
+       TEST(   "ldr    r7, [sp, #160]")
+
+       TEST_RP("str    r",0, VAL1,", [r",0, 24,"]")
+       TEST_P( "ldr    r0, [r",0, 24,"]")
+
+       TEST_GROUP("Generate PC-/SP-relative address")
+
+       TEST("add       r0, pc, #4")
+       TEST("add       r7, pc, #1020")
+       TEST("add       r0, sp, #4")
+       TEST("add       r7, sp, #1020")
+
+       TEST_GROUP("Miscellaneous 16-bit instructions")
+
+       TEST_UNSUPPORTED( "cpsie        i")
+       TEST_UNSUPPORTED( "cpsid        i")
+       TEST_UNSUPPORTED( "setend       le")
+       TEST_UNSUPPORTED( "setend       be")
+
+       TEST("add       sp, #"__stringify(TEST_MEMORY_SIZE)) /* Assumes TEST_MEMORY_SIZE < 0x400 */
+       TEST("sub       sp, #0x7f*4")
+
+DONT_TEST_IN_ITBLOCK(
+       TEST_BF_R(  "cbnz       r",0,0, ", 2f")
+       TEST_BF_R(  "cbz        r",2,-1,", 2f")
+       TEST_BF_RX( "cbnz       r",4,1, ", 2f",0x20)
+       TEST_BF_RX( "cbz        r",7,0, ", 2f",0x40)
+)
+       TEST_R("sxth    r0, r",7, HH1,"")
+       TEST_R("sxth    r7, r",0, HH2,"")
+       TEST_R("sxtb    r0, r",7, HH1,"")
+       TEST_R("sxtb    r7, r",0, HH2,"")
+       TEST_R("uxth    r0, r",7, HH1,"")
+       TEST_R("uxth    r7, r",0, HH2,"")
+       TEST_R("uxtb    r0, r",7, HH1,"")
+       TEST_R("uxtb    r7, r",0, HH2,"")
+       TEST_R("rev     r0, r",7, VAL1,"")
+       TEST_R("rev     r7, r",0, VAL2,"")
+       TEST_R("rev16   r0, r",7, VAL1,"")
+       TEST_R("rev16   r7, r",0, VAL2,"")
+       TEST_UNSUPPORTED(".short 0xba80")
+       TEST_UNSUPPORTED(".short 0xbabf")
+       TEST_R("revsh   r0, r",7, VAL1,"")
+       TEST_R("revsh   r7, r",0, VAL2,"")
+
+#define TEST_POPPC(code, offset)       \
+       TESTCASE_START(code)            \
+       TEST_ARG_PTR(13, offset)        \
+       TEST_ARG_END("")                \
+       TEST_BRANCH_F(code,0)           \
+       TESTCASE_END
+
+       TEST("push      {r0}")
+       TEST("push      {r7}")
+       TEST("push      {r14}")
+       TEST("push      {r0-r7,r14}")
+       TEST("push      {r0,r2,r4,r6,r14}")
+       TEST("push      {r1,r3,r5,r7}")
+       TEST("pop       {r0}")
+       TEST("pop       {r7}")
+       TEST("pop       {r0,r2,r4,r6}")
+       TEST_POPPC("pop {pc}",15*4)
+       TEST_POPPC("pop {r0-r7,pc}",7*4)
+       TEST_POPPC("pop {r1,r3,r5,r7,pc}",11*4)
+       TEST_THUMB_TO_ARM_INTERWORK_P("pop      {pc}    @ ",13,15*4,"")
+       TEST_THUMB_TO_ARM_INTERWORK_P("pop      {r0-r7,pc}      @ ",13,7*4,"")
+
+       TEST_UNSUPPORTED("bkpt.n        0")
+       TEST_UNSUPPORTED("bkpt.n        255")
+
+       TEST_SUPPORTED("yield")
+       TEST("sev")
+       TEST("nop")
+       TEST("wfi")
+       TEST_SUPPORTED("wfe")
+       TEST_UNSUPPORTED(".short 0xbf50") /* Unassigned hints */
+       TEST_UNSUPPORTED(".short 0xbff0") /* Unassigned hints */
+
+#define TEST_IT(code, code2)                   \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       "50:    nop                     \n\t"   \
+       "1:     "code"                  \n\t"   \
+       "       "code2"                 \n\t"   \
+       "2:     nop                     \n\t"   \
+       TESTCASE_END
+
+DONT_TEST_IN_ITBLOCK(
+       TEST_IT("it     eq","moveq r0,#0")
+       TEST_IT("it     vc","movvc r0,#0")
+       TEST_IT("it     le","movle r0,#0")
+       TEST_IT("ite    eq","moveq r0,#0\n\t  movne r1,#1")
+       TEST_IT("itet   vc","movvc r0,#0\n\t  movvs r1,#1\n\t  movvc r2,#2")
+       TEST_IT("itete  le","movle r0,#0\n\t  movgt r1,#1\n\t  movle r2,#2\n\t  movgt r3,#3")
+       TEST_IT("itttt  le","movle r0,#0\n\t  movle r1,#1\n\t  movle r2,#2\n\t  movle r3,#3")
+       TEST_IT("iteee  le","movle r0,#0\n\t  movgt r1,#1\n\t  movgt r2,#2\n\t  movgt r3,#3")
+)
+
+       TEST_GROUP("Load and store multiple")
+
+       TEST_P("ldmia   r",4, 16*4,"!, {r0,r7}")
+       TEST_P("ldmia   r",7, 16*4,"!, {r0-r6}")
+       TEST_P("stmia   r",4, 16*4,"!, {r0,r7}")
+       TEST_P("stmia   r",0, 16*4,"!, {r0-r7}")
+
+       TEST_GROUP("Conditional branch and Supervisor Call instructions")
+
+CONDITION_INSTRUCTIONS(8,
+       TEST_BF("beq    2f")
+       TEST_BB("bne    2b")
+       TEST_BF("bgt    2f")
+       TEST_BB("blt    2b")
+)
+       TEST_UNSUPPORTED(".short 0xde00")
+       TEST_UNSUPPORTED(".short 0xdeff")
+       TEST_UNSUPPORTED("svc   #0x00")
+       TEST_UNSUPPORTED("svc   #0xff")
+
+       TEST_GROUP("Unconditional branch")
+
+       TEST_BF(  "b    2f")
+       TEST_BB(  "b    2b")
+       TEST_BF_X("b    2f", 0x400)
+       TEST_BB_X("b    2b", 0x400)
+
+       TEST_GROUP("Testing instructions in IT blocks")
+
+       TEST_ITBLOCK("subs.n r0, r0")
+
+       verbose("\n");
+}
+
+
+void kprobe_thumb32_test_cases(void)
+{
+       kprobe_test_flags = 0;
+
+       TEST_GROUP("Load/store multiple")
+
+       TEST_UNSUPPORTED("rfedb sp")
+       TEST_UNSUPPORTED("rfeia sp")
+       TEST_UNSUPPORTED("rfedb sp!")
+       TEST_UNSUPPORTED("rfeia sp!")
+
+       TEST_P(   "stmia        r",0, 16*4,", {r0,r8}")
+       TEST_P(   "stmia        r",4, 16*4,", {r0-r12,r14}")
+       TEST_P(   "stmia        r",7, 16*4,"!, {r8-r12,r14}")
+       TEST_P(   "stmia        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+       TEST_P(   "ldmia        r",0, 16*4,", {r0,r8}")
+       TEST_P(   "ldmia        r",4, 0,   ", {r0-r12,r14}")
+       TEST_BF_P("ldmia        r",5, 8*4, "!, {r6-r12,r15}")
+       TEST_P(   "ldmia        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_BF_P("ldmia        r",14,14*4,"!, {r4,pc}")
+
+       TEST_P(   "stmdb        r",0, 16*4,", {r0,r8}")
+       TEST_P(   "stmdb        r",4, 16*4,", {r0-r12,r14}")
+       TEST_P(   "stmdb        r",5, 16*4,"!, {r8-r12,r14}")
+       TEST_P(   "stmdb        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+       TEST_P(   "ldmdb        r",0, 16*4,", {r0,r8}")
+       TEST_P(   "ldmdb        r",4, 16*4,", {r0-r12,r14}")
+       TEST_BF_P("ldmdb        r",5, 16*4,"!, {r6-r12,r15}")
+       TEST_P(   "ldmdb        r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+       TEST_BF_P("ldmdb        r",14,16*4,"!, {r4,pc}")
+
+       TEST_P(   "stmdb        r",13,16*4,"!, {r3-r12,lr}")
+       TEST_P(   "stmdb        r",13,16*4,"!, {r3-r12}")
+       TEST_P(   "stmdb        r",2, 16*4,", {r3-r12,lr}")
+       TEST_P(   "stmdb        r",13,16*4,"!, {r2-r12,lr}")
+       TEST_P(   "stmdb        r",0, 16*4,", {r0-r12}")
+       TEST_P(   "stmdb        r",0, 16*4,", {r0-r12,lr}")
+
+       TEST_BF_P("ldmia        r",13,5*4, "!, {r3-r12,pc}")
+       TEST_P(   "ldmia        r",13,5*4, "!, {r3-r12}")
+       TEST_BF_P("ldmia        r",2, 5*4, "!, {r3-r12,pc}")
+       TEST_BF_P("ldmia        r",13,4*4, "!, {r2-r12,pc}")
+       TEST_P(   "ldmia        r",0, 16*4,", {r0-r12}")
+       TEST_P(   "ldmia        r",0, 16*4,", {r0-r12,lr}")
+
+       TEST_THUMB_TO_ARM_INTERWORK_P("ldmia    r",0,14*4,", {r12,pc}")
+       TEST_THUMB_TO_ARM_INTERWORK_P("ldmia    r",13,2*4,", {r0-r12,pc}")
+
+       TEST_UNSUPPORTED(".short 0xe88f,0x0101  @ stmia pc, {r0,r8}")
+       TEST_UNSUPPORTED(".short 0xe92f,0x5f00  @ stmdb pc!, {r8-r12,r14}")
+       TEST_UNSUPPORTED(".short 0xe8bd,0xc000  @ ldmia r13!, {r14,pc}")
+       TEST_UNSUPPORTED(".short 0xe93e,0xc000  @ ldmdb r14!, {r14,pc}")
+       TEST_UNSUPPORTED(".short 0xe8a7,0x3f00  @ stmia r7!, {r8-r12,sp}")
+       TEST_UNSUPPORTED(".short 0xe8a7,0x9f00  @ stmia r7!, {r8-r12,pc}")
+       TEST_UNSUPPORTED(".short 0xe93e,0x2010  @ ldmdb r14!, {r4,sp}")
+
+       TEST_GROUP("Load/store double or exclusive, table branch")
+
+       TEST_P(  "ldrd  r0, r1, [r",1, 24,", #-16]")
+       TEST(    "ldrd  r12, r14, [sp, #16]")
+       TEST_P(  "ldrd  r1, r0, [r",7, 24,", #-16]!")
+       TEST(    "ldrd  r14, r12, [sp, #16]!")
+       TEST_P(  "ldrd  r1, r0, [r",7, 24,"], #16")
+       TEST(    "ldrd  r7, r8, [sp], #-16")
+
+       TEST_X( "ldrd   r12, r14, 3f",
+               ".align 3                               \n\t"
+               "3:     .word   "__stringify(VAL1)"     \n\t"
+               "       .word   "__stringify(VAL2))
+
+       TEST_UNSUPPORTED(".short 0xe9ff,0xec04  @ ldrd  r14, r12, [pc, #16]!")
+       TEST_UNSUPPORTED(".short 0xe8ff,0xec04  @ ldrd  r14, r12, [pc], #16")
+       TEST_UNSUPPORTED(".short 0xe9d4,0xd800  @ ldrd  sp, r8, [r4]")
+       TEST_UNSUPPORTED(".short 0xe9d4,0xf800  @ ldrd  pc, r8, [r4]")
+       TEST_UNSUPPORTED(".short 0xe9d4,0x7d00  @ ldrd  r7, sp, [r4]")
+       TEST_UNSUPPORTED(".short 0xe9d4,0x7f00  @ ldrd  r7, pc, [r4]")
+
+       TEST_RRP("strd  r",0, VAL1,", r",1, VAL2,", [r",1, 24,", #-16]")
+       TEST_RR( "strd  r",12,VAL2,", r",14,VAL1,", [sp, #16]")
+       TEST_RRP("strd  r",1, VAL1,", r",0, VAL2,", [r",7, 24,", #-16]!")
+       TEST_RR( "strd  r",14,VAL2,", r",12,VAL1,", [sp, #16]!")
+       TEST_RRP("strd  r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16")
+       TEST_RR( "strd  r",7, VAL2,", r",8, VAL1,", [sp], #-16")
+       TEST_UNSUPPORTED(".short 0xe9ef,0xec04  @ strd  r14, r12, [pc, #16]!")
+       TEST_UNSUPPORTED(".short 0xe8ef,0xec04  @ strd  r14, r12, [pc], #16")
+
+       TEST_RX("tbb    [pc, r",0, (9f-(1f+4)),"]",
+               "9:                     \n\t"
+               ".byte  (2f-1b-4)>>1    \n\t"
+               ".byte  (3f-1b-4)>>1    \n\t"
+               "3:     mvn     r0, r0  \n\t"
+               "2:     nop             \n\t")
+
+       TEST_RX("tbb    [pc, r",4, (9f-(1f+4)+1),"]",
+               "9:                     \n\t"
+               ".byte  (2f-1b-4)>>1    \n\t"
+               ".byte  (3f-1b-4)>>1    \n\t"
+               "3:     mvn     r0, r0  \n\t"
+               "2:     nop             \n\t")
+
+       TEST_RRX("tbb   [r",1,9f,", r",2,0,"]",
+               "9:                     \n\t"
+               ".byte  (2f-1b-4)>>1    \n\t"
+               ".byte  (3f-1b-4)>>1    \n\t"
+               "3:     mvn     r0, r0  \n\t"
+               "2:     nop             \n\t")
+
+       TEST_RX("tbh    [pc, r",7, (9f-(1f+4))>>1,"]",
+               "9:                     \n\t"
+               ".short (2f-1b-4)>>1    \n\t"
+               ".short (3f-1b-4)>>1    \n\t"
+               "3:     mvn     r0, r0  \n\t"
+               "2:     nop             \n\t")
+
+       TEST_RX("tbh    [pc, r",12, ((9f-(1f+4))>>1)+1,"]",
+               "9:                     \n\t"
+               ".short (2f-1b-4)>>1    \n\t"
+               ".short (3f-1b-4)>>1    \n\t"
+               "3:     mvn     r0, r0  \n\t"
+               "2:     nop             \n\t")
+
+       TEST_RRX("tbh   [r",1,9f, ", r",14,1,"]",
+               "9:                     \n\t"
+               ".short (2f-1b-4)>>1    \n\t"
+               ".short (3f-1b-4)>>1    \n\t"
+               "3:     mvn     r0, r0  \n\t"
+               "2:     nop             \n\t")
+
+       TEST_UNSUPPORTED(".short 0xe8d1,0xf01f  @ tbh [r1, pc]")
+       TEST_UNSUPPORTED(".short 0xe8d1,0xf01d  @ tbh [r1, sp]")
+       TEST_UNSUPPORTED(".short 0xe8dd,0xf012  @ tbh [sp, r2]")
+
+       TEST_UNSUPPORTED("strexb        r0, r1, [r2]")
+       TEST_UNSUPPORTED("strexh        r0, r1, [r2]")
+       TEST_UNSUPPORTED("strexd        r0, r1, [r2]")
+       TEST_UNSUPPORTED("ldrexb        r0, [r1]")
+       TEST_UNSUPPORTED("ldrexh        r0, [r1]")
+       TEST_UNSUPPORTED("ldrexd        r0, [r1]")
+
+       TEST_GROUP("Data-processing (shifted register) and (modified immediate)")
+
+#define _DATA_PROCESSING32_DNM(op,s,val)                                       \
+       TEST_RR(op s".w r0,  r",1, VAL1,", r",2, val, "")                       \
+       TEST_RR(op s"   r1,  r",1, VAL1,", r",2, val, ", lsl #3")               \
+       TEST_RR(op s"   r2,  r",3, VAL1,", r",2, val, ", lsr #4")               \
+       TEST_RR(op s"   r3,  r",3, VAL1,", r",2, val, ", asr #5")               \
+       TEST_RR(op s"   r4,  r",5, VAL1,", r",2, N(val),", asr #6")             \
+       TEST_RR(op s"   r5,  r",5, VAL1,", r",2, val, ", ror #7")               \
+       TEST_RR(op s"   r8,  r",9, VAL1,", r",10,val, ", rrx")                  \
+       TEST_R( op s"   r0,  r",11,VAL1,", #0x00010001")                        \
+       TEST_R( op s"   r11, r",0, VAL1,", #0xf5000000")                        \
+       TEST_R( op s"   r7,  r",8, VAL2,", #0x000af000")
+
+#define DATA_PROCESSING32_DNM(op,val)          \
+       _DATA_PROCESSING32_DNM(op,"",val)       \
+       _DATA_PROCESSING32_DNM(op,"s",val)
+
+#define DATA_PROCESSING32_NM(op,val)                                   \
+       TEST_RR(op".w   r",1, VAL1,", r",2, val, "")                    \
+       TEST_RR(op"     r",1, VAL1,", r",2, val, ", lsl #3")            \
+       TEST_RR(op"     r",3, VAL1,", r",2, val, ", lsr #4")            \
+       TEST_RR(op"     r",3, VAL1,", r",2, val, ", asr #5")            \
+       TEST_RR(op"     r",5, VAL1,", r",2, N(val),", asr #6")          \
+       TEST_RR(op"     r",5, VAL1,", r",2, val, ", ror #7")            \
+       TEST_RR(op"     r",9, VAL1,", r",10,val, ", rrx")               \
+       TEST_R( op"     r",11,VAL1,", #0x00010001")                     \
+       TEST_R( op"     r",0, VAL1,", #0xf5000000")                     \
+       TEST_R( op"     r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING32_DM(op,s,val)                                \
+       TEST_R( op s".w r0,  r",14, val, "")                    \
+       TEST_R( op s"   r1,  r",12, val, ", lsl #3")            \
+       TEST_R( op s"   r2,  r",11, val, ", lsr #4")            \
+       TEST_R( op s"   r3,  r",10, val, ", asr #5")            \
+       TEST_R( op s"   r4,  r",9, N(val),", asr #6")           \
+       TEST_R( op s"   r5,  r",8, val, ", ror #7")             \
+       TEST_R( op s"   r8,  r",7,val, ", rrx")                 \
+       TEST(   op s"   r0,  #0x00010001")                      \
+       TEST(   op s"   r11, #0xf5000000")                      \
+       TEST(   op s"   r7,  #0x000af000")                      \
+       TEST(   op s"   r4,  #0x00005a00")
+
+#define DATA_PROCESSING32_DM(op,val)           \
+       _DATA_PROCESSING32_DM(op,"",val)        \
+       _DATA_PROCESSING32_DM(op,"s",val)
+
+       DATA_PROCESSING32_DNM("and",0xf00f00ff)
+       DATA_PROCESSING32_NM("tst",0xf00f00ff)
+       DATA_PROCESSING32_DNM("bic",0xf00f00ff)
+       DATA_PROCESSING32_DNM("orr",0xf00f00ff)
+       DATA_PROCESSING32_DM("mov",VAL2)
+       DATA_PROCESSING32_DNM("orn",0xf00f00ff)
+       DATA_PROCESSING32_DM("mvn",VAL2)
+       DATA_PROCESSING32_DNM("eor",0xf00f00ff)
+       DATA_PROCESSING32_NM("teq",0xf00f00ff)
+       DATA_PROCESSING32_DNM("add",VAL2)
+       DATA_PROCESSING32_NM("cmn",VAL2)
+       DATA_PROCESSING32_DNM("adc",VAL2)
+       DATA_PROCESSING32_DNM("sbc",VAL2)
+       DATA_PROCESSING32_DNM("sub",VAL2)
+       DATA_PROCESSING32_NM("cmp",VAL2)
+       DATA_PROCESSING32_DNM("rsb",VAL2)
+
+       TEST_RR("pkhbt  r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR("pkhbt  r14,r",12, HH1,", r",10,HH2,", lsl #2")
+       TEST_RR("pkhtb  r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR("pkhtb  r14,r",12, HH1,", r",10,HH2,", asr #2")
+
+       TEST_UNSUPPORTED(".short 0xea17,0x0f0d  @ tst.w r7, sp")
+       TEST_UNSUPPORTED(".short 0xea17,0x0f0f  @ tst.w r7, pc")
+       TEST_UNSUPPORTED(".short 0xea1d,0x0f07  @ tst.w sp, r7")
+       TEST_UNSUPPORTED(".short 0xea1f,0x0f07  @ tst.w pc, r7")
+       TEST_UNSUPPORTED(".short 0xf01d,0x1f08  @ tst sp, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf01f,0x1f08  @ tst pc, #0x00080008")
+
+       TEST_UNSUPPORTED(".short 0xea97,0x0f0d  @ teq.w r7, sp")
+       TEST_UNSUPPORTED(".short 0xea97,0x0f0f  @ teq.w r7, pc")
+       TEST_UNSUPPORTED(".short 0xea9d,0x0f07  @ teq.w sp, r7")
+       TEST_UNSUPPORTED(".short 0xea9f,0x0f07  @ teq.w pc, r7")
+       TEST_UNSUPPORTED(".short 0xf09d,0x1f08  @ tst sp, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf09f,0x1f08  @ tst pc, #0x00080008")
+
+       TEST_UNSUPPORTED(".short 0xeb17,0x0f0d  @ cmn.w r7, sp")
+       TEST_UNSUPPORTED(".short 0xeb17,0x0f0f  @ cmn.w r7, pc")
+       TEST_P("cmn.w   sp, r",7,0,"")
+       TEST_UNSUPPORTED(".short 0xeb1f,0x0f07  @ cmn.w pc, r7")
+       TEST(  "cmn     sp, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf11f,0x1f08  @ cmn pc, #0x00080008")
+
+       TEST_UNSUPPORTED(".short 0xebb7,0x0f0d  @ cmp.w r7, sp")
+       TEST_UNSUPPORTED(".short 0xebb7,0x0f0f  @ cmp.w r7, pc")
+       TEST_P("cmp.w   sp, r",7,0,"")
+       TEST_UNSUPPORTED(".short 0xebbf,0x0f07  @ cmp.w pc, r7")
+       TEST(  "cmp     sp, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf1bf,0x1f08  @ cmp pc, #0x00080008")
+
+       TEST_UNSUPPORTED(".short 0xea5f,0x070d  @ movs.w r7, sp")
+       TEST_UNSUPPORTED(".short 0xea5f,0x070f  @ movs.w r7, pc")
+       TEST_UNSUPPORTED(".short 0xea5f,0x0d07  @ movs.w sp, r7")
+       TEST_UNSUPPORTED(".short 0xea4f,0x0f07  @ mov.w  pc, r7")
+       TEST_UNSUPPORTED(".short 0xf04f,0x1d08  @ mov sp, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf04f,0x1f08  @ mov pc, #0x00080008")
+
+       TEST_R("add.w   r0, sp, r",1, 4,"")
+       TEST_R("adds    r0, sp, r",1, 4,", asl #3")
+       TEST_R("add     r0, sp, r",1, 4,", asl #4")
+       TEST_R("add     r0, sp, r",1, 16,", ror #1")
+       TEST_R("add.w   sp, sp, r",1, 4,"")
+       TEST_R("add     sp, sp, r",1, 4,", asl #3")
+       TEST_UNSUPPORTED(".short 0xeb0d,0x1d01  @ add sp, sp, r1, asl #4")
+       TEST_UNSUPPORTED(".short 0xeb0d,0x0d71  @ add sp, sp, r1, ror #1")
+       TEST(  "add.w   r0, sp, #24")
+       TEST(  "add.w   sp, sp, #24")
+       TEST_UNSUPPORTED(".short 0xeb0d,0x0f01  @ add pc, sp, r1")
+       TEST_UNSUPPORTED(".short 0xeb0d,0x000f  @ add r0, sp, pc")
+       TEST_UNSUPPORTED(".short 0xeb0d,0x000d  @ add r0, sp, sp")
+       TEST_UNSUPPORTED(".short 0xeb0d,0x0d0f  @ add sp, sp, pc")
+       TEST_UNSUPPORTED(".short 0xeb0d,0x0d0d  @ add sp, sp, sp")
+
+       TEST_R("sub.w   r0, sp, r",1, 4,"")
+       TEST_R("subs    r0, sp, r",1, 4,", asl #3")
+       TEST_R("sub     r0, sp, r",1, 4,", asl #4")
+       TEST_R("sub     r0, sp, r",1, 16,", ror #1")
+       TEST_R("sub.w   sp, sp, r",1, 4,"")
+       TEST_R("sub     sp, sp, r",1, 4,", asl #3")
+       TEST_UNSUPPORTED(".short 0xebad,0x1d01  @ sub sp, sp, r1, asl #4")
+       TEST_UNSUPPORTED(".short 0xebad,0x0d71  @ sub sp, sp, r1, ror #1")
+       TEST_UNSUPPORTED(".short 0xebad,0x0f01  @ sub pc, sp, r1")
+       TEST(  "sub.w   r0, sp, #24")
+       TEST(  "sub.w   sp, sp, #24")
+
+       TEST_UNSUPPORTED(".short 0xea02,0x010f  @ and r1, r2, pc")
+       TEST_UNSUPPORTED(".short 0xea0f,0x0103  @ and r1, pc, r3")
+       TEST_UNSUPPORTED(".short 0xea02,0x0f03  @ and pc, r2, r3")
+       TEST_UNSUPPORTED(".short 0xea02,0x010d  @ and r1, r2, sp")
+       TEST_UNSUPPORTED(".short 0xea0d,0x0103  @ and r1, sp, r3")
+       TEST_UNSUPPORTED(".short 0xea02,0x0d03  @ and sp, r2, r3")
+       TEST_UNSUPPORTED(".short 0xf00d,0x1108  @ and r1, sp, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf00f,0x1108  @ and r1, pc, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf002,0x1d08  @ and sp, r8, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf002,0x1f08  @ and pc, r8, #0x00080008")
+
+       TEST_UNSUPPORTED(".short 0xeb02,0x010f  @ add r1, r2, pc")
+       TEST_UNSUPPORTED(".short 0xeb0f,0x0103  @ add r1, pc, r3")
+       TEST_UNSUPPORTED(".short 0xeb02,0x0f03  @ add pc, r2, r3")
+       TEST_UNSUPPORTED(".short 0xeb02,0x010d  @ add r1, r2, sp")
+       TEST_SUPPORTED(  ".short 0xeb0d,0x0103  @ add r1, sp, r3")
+       TEST_UNSUPPORTED(".short 0xeb02,0x0d03  @ add sp, r2, r3")
+       TEST_SUPPORTED(  ".short 0xf10d,0x1108  @ add r1, sp, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf10d,0x1f08  @ add pc, sp, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf10f,0x1108  @ add r1, pc, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf102,0x1d08  @ add sp, r8, #0x00080008")
+       TEST_UNSUPPORTED(".short 0xf102,0x1f08  @ add pc, r8, #0x00080008")
+
+       TEST_UNSUPPORTED(".short 0xeaa0,0x0000")
+       TEST_UNSUPPORTED(".short 0xeaf0,0x0000")
+       TEST_UNSUPPORTED(".short 0xeb20,0x0000")
+       TEST_UNSUPPORTED(".short 0xeb80,0x0000")
+       TEST_UNSUPPORTED(".short 0xebe0,0x0000")
+
+       TEST_UNSUPPORTED(".short 0xf0a0,0x0000")
+       TEST_UNSUPPORTED(".short 0xf0c0,0x0000")
+       TEST_UNSUPPORTED(".short 0xf0f0,0x0000")
+       TEST_UNSUPPORTED(".short 0xf120,0x0000")
+       TEST_UNSUPPORTED(".short 0xf180,0x0000")
+       TEST_UNSUPPORTED(".short 0xf1e0,0x0000")
+
+       TEST_GROUP("Coprocessor instructions")
+
+       TEST_UNSUPPORTED(".short 0xec00,0x0000")
+       TEST_UNSUPPORTED(".short 0xeff0,0x0000")
+       TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+       TEST_UNSUPPORTED(".short 0xfff0,0x0000")
+
+       TEST_GROUP("Data-processing (plain binary immediate)")
+
+       TEST_R("addw    r0,  r",1, VAL1,", #0x123")
+       TEST(  "addw    r14, sp, #0xf5a")
+       TEST(  "addw    sp, sp, #0x20")
+       TEST(  "addw    r7,  pc, #0x888")
+       TEST_UNSUPPORTED(".short 0xf20f,0x1f20  @ addw pc, pc, #0x120")
+       TEST_UNSUPPORTED(".short 0xf20d,0x1f20  @ addw pc, sp, #0x120")
+       TEST_UNSUPPORTED(".short 0xf20f,0x1d20  @ addw sp, pc, #0x120")
+       TEST_UNSUPPORTED(".short 0xf200,0x1d20  @ addw sp, r0, #0x120")
+
+       TEST_R("subw    r0,  r",1, VAL1,", #0x123")
+       TEST(  "subw    r14, sp, #0xf5a")
+       TEST(  "subw    sp, sp, #0x20")
+       TEST(  "subw    r7,  pc, #0x888")
+       TEST_UNSUPPORTED(".short 0xf2af,0x1f20  @ subw pc, pc, #0x120")
+       TEST_UNSUPPORTED(".short 0xf2ad,0x1f20  @ subw pc, sp, #0x120")
+       TEST_UNSUPPORTED(".short 0xf2af,0x1d20  @ subw sp, pc, #0x120")
+       TEST_UNSUPPORTED(".short 0xf2a0,0x1d20  @ subw sp, r0, #0x120")
+
+       TEST("movw      r0, #0")
+       TEST("movw      r0, #0xffff")
+       TEST("movw      lr, #0xffff")
+       TEST_UNSUPPORTED(".short 0xf240,0x0d00  @ movw sp, #0")
+       TEST_UNSUPPORTED(".short 0xf240,0x0f00  @ movw pc, #0")
+
+       TEST_R("movt    r",0, VAL1,", #0")
+       TEST_R("movt    r",0, VAL2,", #0xffff")
+       TEST_R("movt    r",14,VAL1,", #0xffff")
+       TEST_UNSUPPORTED(".short 0xf2c0,0x0d00  @ movt sp, #0")
+       TEST_UNSUPPORTED(".short 0xf2c0,0x0f00  @ movt pc, #0")
+
+       TEST_R(     "ssat       r0, #24, r",0,   VAL1,"")
+       TEST_R(     "ssat       r14, #24, r",12, VAL2,"")
+       TEST_R(     "ssat       r0, #24, r",0,   VAL1,", lsl #8")
+       TEST_R(     "ssat       r14, #24, r",12, VAL2,", asr #8")
+       TEST_UNSUPPORTED(".short 0xf30c,0x0d17  @ ssat  sp, #24, r12")
+       TEST_UNSUPPORTED(".short 0xf30c,0x0f17  @ ssat  pc, #24, r12")
+       TEST_UNSUPPORTED(".short 0xf30d,0x0c17  @ ssat  r12, #24, sp")
+       TEST_UNSUPPORTED(".short 0xf30f,0x0c17  @ ssat  r12, #24, pc")
+
+       TEST_R(     "usat       r0, #24, r",0,   VAL1,"")
+       TEST_R(     "usat       r14, #24, r",12, VAL2,"")
+       TEST_R(     "usat       r0, #24, r",0,   VAL1,", lsl #8")
+       TEST_R(     "usat       r14, #24, r",12, VAL2,", asr #8")
+       TEST_UNSUPPORTED(".short 0xf38c,0x0d17  @ usat  sp, #24, r12")
+       TEST_UNSUPPORTED(".short 0xf38c,0x0f17  @ usat  pc, #24, r12")
+       TEST_UNSUPPORTED(".short 0xf38d,0x0c17  @ usat  r12, #24, sp")
+       TEST_UNSUPPORTED(".short 0xf38f,0x0c17  @ usat  r12, #24, pc")
+
+       TEST_R(     "ssat16     r0, #12, r",0,   HH1,"")
+       TEST_R(     "ssat16     r14, #12, r",12, HH2,"")
+       TEST_UNSUPPORTED(".short 0xf32c,0x0d0b  @ ssat16        sp, #12, r12")
+       TEST_UNSUPPORTED(".short 0xf32c,0x0f0b  @ ssat16        pc, #12, r12")
+       TEST_UNSUPPORTED(".short 0xf32d,0x0c0b  @ ssat16        r12, #12, sp")
+       TEST_UNSUPPORTED(".short 0xf32f,0x0c0b  @ ssat16        r12, #12, pc")
+
+       TEST_R(     "usat16     r0, #12, r",0,   HH1,"")
+       TEST_R(     "usat16     r14, #12, r",12, HH2,"")
+       TEST_UNSUPPORTED(".short 0xf3ac,0x0d0b  @ usat16        sp, #12, r12")
+       TEST_UNSUPPORTED(".short 0xf3ac,0x0f0b  @ usat16        pc, #12, r12")
+       TEST_UNSUPPORTED(".short 0xf3ad,0x0c0b  @ usat16        r12, #12, sp")
+       TEST_UNSUPPORTED(".short 0xf3af,0x0c0b  @ usat16        r12, #12, pc")
+
+       TEST_R(     "sbfx       r0, r",0  , VAL1,", #0, #31")
+       TEST_R(     "sbfx       r14, r",12, VAL2,", #8, #16")
+       TEST_R(     "sbfx       r4, r",10,  VAL1,", #16, #15")
+       TEST_UNSUPPORTED(".short 0xf34c,0x2d0f  @ sbfx  sp, r12, #8, #16")
+       TEST_UNSUPPORTED(".short 0xf34c,0x2f0f  @ sbfx  pc, r12, #8, #16")
+       TEST_UNSUPPORTED(".short 0xf34d,0x2c0f  @ sbfx  r12, sp, #8, #16")
+       TEST_UNSUPPORTED(".short 0xf34f,0x2c0f  @ sbfx  r12, pc, #8, #16")
+
+       TEST_R(     "ubfx       r0, r",0  , VAL1,", #0, #31")
+       TEST_R(     "ubfx       r14, r",12, VAL2,", #8, #16")
+       TEST_R(     "ubfx       r4, r",10,  VAL1,", #16, #15")
+       TEST_UNSUPPORTED(".short 0xf3cc,0x2d0f  @ ubfx  sp, r12, #8, #16")
+       TEST_UNSUPPORTED(".short 0xf3cc,0x2f0f  @ ubfx  pc, r12, #8, #16")
+       TEST_UNSUPPORTED(".short 0xf3cd,0x2c0f  @ ubfx  r12, sp, #8, #16")
+       TEST_UNSUPPORTED(".short 0xf3cf,0x2c0f  @ ubfx  r12, pc, #8, #16")
+
+       TEST_R(     "bfc        r",0, VAL1,", #4, #20")
+       TEST_R(     "bfc        r",14,VAL2,", #4, #20")
+       TEST_R(     "bfc        r",7, VAL1,", #0, #31")
+       TEST_R(     "bfc        r",8, VAL2,", #0, #31")
+       TEST_UNSUPPORTED(".short 0xf36f,0x0d1e  @ bfc   sp, #0, #31")
+       TEST_UNSUPPORTED(".short 0xf36f,0x0f1e  @ bfc   pc, #0, #31")
+
+       TEST_RR(    "bfi        r",0, VAL1,", r",0  , VAL2,", #0, #31")
+       TEST_RR(    "bfi        r",12,VAL1,", r",14 , VAL2,", #4, #20")
+       TEST_UNSUPPORTED(".short 0xf36e,0x1d17  @ bfi   sp, r14, #4, #20")
+       TEST_UNSUPPORTED(".short 0xf36e,0x1f17  @ bfi   pc, r14, #4, #20")
+       TEST_UNSUPPORTED(".short 0xf36d,0x1e17  @ bfi   r14, sp, #4, #20")
+
+       TEST_GROUP("Branches and miscellaneous control")
+
+CONDITION_INSTRUCTIONS(22,
+       TEST_BF("beq.w  2f")
+       TEST_BB("bne.w  2b")
+       TEST_BF("bgt.w  2f")
+       TEST_BB("blt.w  2b")
+       TEST_BF_X("bpl.w        2f",0x1000)
+)
+
+       TEST_UNSUPPORTED("msr   cpsr, r0")
+       TEST_UNSUPPORTED("msr   cpsr_f, r1")
+       TEST_UNSUPPORTED("msr   spsr, r2")
+
+       TEST_UNSUPPORTED("cpsie.w       i")
+       TEST_UNSUPPORTED("cpsid.w       i")
+       TEST_UNSUPPORTED("cps   0x13")
+
+       TEST_SUPPORTED("yield.w")
+       TEST("sev.w")
+       TEST("nop.w")
+       TEST("wfi.w")
+       TEST_SUPPORTED("wfe.w")
+       TEST_UNSUPPORTED("dbg.w #0")
+
+       TEST_UNSUPPORTED("clrex")
+       TEST_UNSUPPORTED("dsb")
+       TEST_UNSUPPORTED("dmb")
+       TEST_UNSUPPORTED("isb")
+
+       TEST_UNSUPPORTED("bxj   r0")
+
+       TEST_UNSUPPORTED("subs  pc, lr, #4")
+
+       TEST("mrs       r0, cpsr")
+       TEST("mrs       r14, cpsr")
+       TEST_UNSUPPORTED(".short 0xf3ef,0x8d00  @ mrs   sp, spsr")
+       TEST_UNSUPPORTED(".short 0xf3ef,0x8f00  @ mrs   pc, spsr")
+       TEST_UNSUPPORTED("mrs   r0, spsr")
+       TEST_UNSUPPORTED("mrs   lr, spsr")
+
+       TEST_UNSUPPORTED(".short 0xf7f0,0x8000 @ smc #0")
+
+       TEST_UNSUPPORTED(".short 0xf7f0,0xa000 @ undefeined")
+
+       TEST_BF(  "b.w  2f")
+       TEST_BB(  "b.w  2b")
+       TEST_BF_X("b.w  2f", 0x1000)
+
+       TEST_BF(  "bl.w 2f")
+       TEST_BB(  "bl.w 2b")
+       TEST_BB_X("bl.w 2b", 0x1000)
+
+       TEST_X( "blx    __dummy_arm_subroutine",
+               ".arm                           \n\t"
+               ".align                         \n\t"
+               ".type __dummy_arm_subroutine, %%function \n\t"
+               "__dummy_arm_subroutine:        \n\t"
+               "mov    r0, pc                  \n\t"
+               "bx     lr                      \n\t"
+               ".thumb                         \n\t"
+       )
+       TEST(   "blx    __dummy_arm_subroutine")
+
+       TEST_GROUP("Store single data item")
+
+#define SINGLE_STORE(size)                                                     \
+       TEST_RP( "str"size"     r",0, VAL1,", [r",11,-1024,", #1024]")          \
+       TEST_RP( "str"size"     r",14,VAL2,", [r",1, -1024,", #1080]")          \
+       TEST_RP( "str"size"     r",0, VAL1,", [r",11,256,  ", #-120]")          \
+       TEST_RP( "str"size"     r",14,VAL2,", [r",1, 256,  ", #-128]")          \
+       TEST_RP( "str"size"     r",0, VAL1,", [r",11,24,  "], #120")            \
+       TEST_RP( "str"size"     r",14,VAL2,", [r",1, 24,  "], #128")            \
+       TEST_RP( "str"size"     r",0, VAL1,", [r",11,24,  "], #-120")           \
+       TEST_RP( "str"size"     r",14,VAL2,", [r",1, 24,  "], #-128")           \
+       TEST_RP( "str"size"     r",0, VAL1,", [r",11,24,   ", #120]!")          \
+       TEST_RP( "str"size"     r",14,VAL2,", [r",1, 24,   ", #128]!")          \
+       TEST_RP( "str"size"     r",0, VAL1,", [r",11,256,  ", #-120]!")         \
+       TEST_RP( "str"size"     r",14,VAL2,", [r",1, 256,  ", #-128]!")         \
+       TEST_RPR("str"size".w   r",0, VAL1,", [r",1, 0,", r",2, 4,"]")          \
+       TEST_RPR("str"size"     r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]")  \
+       TEST_R(  "str"size".w   r",7, VAL1,", [sp, #24]")                       \
+       TEST_RP( "str"size".w   r",0, VAL2,", [r",0,0, "]")                     \
+       TEST_UNSUPPORTED("str"size"t    r0, [r1, #4]")
+
+       SINGLE_STORE("b")
+       SINGLE_STORE("h")
+       SINGLE_STORE("")
+
+       TEST("str       sp, [sp]")
+       TEST_UNSUPPORTED(".short 0xf8cf,0xe000  @ str   r14, [pc]")
+       TEST_UNSUPPORTED(".short 0xf8ce,0xf000  @ str   pc, [r14]")
+
+       TEST_GROUP("Advanced SIMD element or structure load/store instructions")
+
+       TEST_UNSUPPORTED(".short 0xf900,0x0000")
+       TEST_UNSUPPORTED(".short 0xf92f,0xffff")
+       TEST_UNSUPPORTED(".short 0xf980,0x0000")
+       TEST_UNSUPPORTED(".short 0xf9ef,0xffff")
+
+       TEST_GROUP("Load single data item and memory hints")
+
+#define SINGLE_LOAD(size)                                              \
+       TEST_P( "ldr"size"      r0, [r",11,-1024, ", #1024]")           \
+       TEST_P( "ldr"size"      r14, [r",1, -1024,", #1080]")           \
+       TEST_P( "ldr"size"      r0, [r",11,256,   ", #-120]")           \
+       TEST_P( "ldr"size"      r14, [r",1, 256,  ", #-128]")           \
+       TEST_P( "ldr"size"      r0, [r",11,24,   "], #120")             \
+       TEST_P( "ldr"size"      r14, [r",1, 24,  "], #128")             \
+       TEST_P( "ldr"size"      r0, [r",11,24,   "], #-120")            \
+       TEST_P( "ldr"size"      r14, [r",1,24,   "], #-128")            \
+       TEST_P( "ldr"size"      r0, [r",11,24,    ", #120]!")           \
+       TEST_P( "ldr"size"      r14, [r",1, 24,   ", #128]!")           \
+       TEST_P( "ldr"size"      r0, [r",11,256,   ", #-120]!")          \
+       TEST_P( "ldr"size"      r14, [r",1, 256,  ", #-128]!")          \
+       TEST_PR("ldr"size".w    r0, [r",1, 0,", r",2, 4,"]")            \
+       TEST_PR("ldr"size"      r14, [r",10,0,", r",11,4,", lsl #1]")   \
+       TEST_X( "ldr"size".w    r0, 3f",                                \
+               ".align 3                               \n\t"           \
+               "3:     .word   "__stringify(VAL1))                     \
+       TEST_X( "ldr"size".w    r14, 3f",                               \
+               ".align 3                               \n\t"           \
+               "3:     .word   "__stringify(VAL2))                     \
+       TEST(   "ldr"size".w    r7, 3b")                                \
+       TEST(   "ldr"size".w    r7, [sp, #24]")                         \
+       TEST_P( "ldr"size".w    r0, [r",0,0, "]")                       \
+       TEST_UNSUPPORTED("ldr"size"t    r0, [r1, #4]")
+
+       SINGLE_LOAD("b")
+       SINGLE_LOAD("sb")
+       SINGLE_LOAD("h")
+       SINGLE_LOAD("sh")
+       SINGLE_LOAD("")
+
+       TEST_BF_P("ldr  pc, [r",14, 15*4,"]")
+       TEST_P(   "ldr  sp, [r",14, 13*4,"]")
+       TEST_BF_R("ldr  pc, [sp, r",14, 15*4,"]")
+       TEST_R(   "ldr  sp, [sp, r",14, 13*4,"]")
+       TEST_THUMB_TO_ARM_INTERWORK_P("ldr      pc, [r",0,0,", #15*4]")
+       TEST_SUPPORTED("ldr     sp, 99f")
+       TEST_SUPPORTED("ldr     pc, 99f")
+
+       TEST_UNSUPPORTED(".short 0xf854,0x700d  @ ldr   r7, [r4, sp]")
+       TEST_UNSUPPORTED(".short 0xf854,0x700f  @ ldr   r7, [r4, pc]")
+       TEST_UNSUPPORTED(".short 0xf814,0x700d  @ ldrb  r7, [r4, sp]")
+       TEST_UNSUPPORTED(".short 0xf814,0x700f  @ ldrb  r7, [r4, pc]")
+       TEST_UNSUPPORTED(".short 0xf89f,0xd004  @ ldrb  sp, 99f")
+       TEST_UNSUPPORTED(".short 0xf814,0xd008  @ ldrb  sp, [r4, r8]")
+       TEST_UNSUPPORTED(".short 0xf894,0xd000  @ ldrb  sp, [r4]")
+
+       TEST_UNSUPPORTED(".short 0xf860,0x0000") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xf9ff,0xffff") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xf950,0x0000") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xf95f,0xffff") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xf800,0x0800") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xf97f,0xfaff") /* Unallocated space */
+
+       TEST(   "pli    [pc, #4]")
+       TEST(   "pli    [pc, #-4]")
+       TEST(   "pld    [pc, #4]")
+       TEST(   "pld    [pc, #-4]")
+
+       TEST_P( "pld    [r",0,-1024,", #1024]")
+       TEST(   ".short 0xf8b0,0xf400   @ pldw  [r0, #1024]")
+       TEST_P( "pli    [r",4, 0b,", #1024]")
+       TEST_P( "pld    [r",7, 120,", #-120]")
+       TEST(   ".short 0xf837,0xfc78   @ pldw  [r7, #-120]")
+       TEST_P( "pli    [r",11,120,", #-120]")
+       TEST(   "pld    [sp, #0]")
+
+       TEST_PR("pld    [r",7, 24, ", r",0, 16,"]")
+       TEST_PR("pld    [r",8, 24, ", r",12,16,", lsl #3]")
+       TEST_SUPPORTED(".short 0xf837,0xf000    @ pldw  [r7, r0]")
+       TEST_SUPPORTED(".short 0xf838,0xf03c    @ pldw  [r8, r12, lsl #3]");
+       TEST_RR("pli    [r",12,0b,", r",0, 16,"]")
+       TEST_RR("pli    [r",0, 0b,", r",12,16,", lsl #3]")
+       TEST_R( "pld    [sp, r",1, 16,"]")
+       TEST_UNSUPPORTED(".short 0xf817,0xf00d  @pld    [r7, sp]")
+       TEST_UNSUPPORTED(".short 0xf817,0xf00f  @pld    [r7, pc]")
+
+       TEST_GROUP("Data-processing (register)")
+
+#define SHIFTS32(op)                                   \
+       TEST_RR(op"     r0,  r",1, VAL1,", r",2, 3, "") \
+       TEST_RR(op"     r14, r",12,VAL2,", r",11,10,"")
+
+       SHIFTS32("lsl")
+       SHIFTS32("lsls")
+       SHIFTS32("lsr")
+       SHIFTS32("lsrs")
+       SHIFTS32("asr")
+       SHIFTS32("asrs")
+       SHIFTS32("ror")
+       SHIFTS32("rors")
+
+       TEST_UNSUPPORTED(".short 0xfa01,0xff02  @ lsl   pc, r1, r2")
+       TEST_UNSUPPORTED(".short 0xfa01,0xfd02  @ lsl   sp, r1, r2")
+       TEST_UNSUPPORTED(".short 0xfa0f,0xf002  @ lsl   r0, pc, r2")
+       TEST_UNSUPPORTED(".short 0xfa0d,0xf002  @ lsl   r0, sp, r2")
+       TEST_UNSUPPORTED(".short 0xfa01,0xf00f  @ lsl   r0, r1, pc")
+       TEST_UNSUPPORTED(".short 0xfa01,0xf00d  @ lsl   r0, r1, sp")
+
+       TEST_RR(    "sxtah      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sxtah      r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "sxth       r8, r",7,  HH1,"")
+
+       TEST_UNSUPPORTED(".short 0xfa0f,0xff87  @ sxth  pc, r7");
+       TEST_UNSUPPORTED(".short 0xfa0f,0xfd87  @ sxth  sp, r7");
+       TEST_UNSUPPORTED(".short 0xfa0f,0xf88f  @ sxth  r8, pc");
+       TEST_UNSUPPORTED(".short 0xfa0f,0xf88d  @ sxth  r8, sp");
+
+       TEST_RR(    "uxtah      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uxtah      r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "uxth       r8, r",7,  HH1,"")
+
+       TEST_RR(    "sxtab16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sxtab16    r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "sxtb16     r8, r",7,  HH1,"")
+
+       TEST_RR(    "uxtab16    r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uxtab16    r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "uxtb16     r8, r",7,  HH1,"")
+
+       TEST_RR(    "sxtab      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "sxtab      r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "sxtb       r8, r",7,  HH1,"")
+
+       TEST_RR(    "uxtab      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "uxtab      r14,r",12, HH2,", r",10,HH1,", ror #8")
+       TEST_R(     "uxtb       r8, r",7,  HH1,"")
+
+       TEST_UNSUPPORTED(".short 0xfa60,0x00f0")
+       TEST_UNSUPPORTED(".short 0xfa7f,0xffff")
+
+#define PARALLEL_ADD_SUB(op)                                   \
+       TEST_RR(  op"add16      r0, r",0,  HH1,", r",1, HH2,"") \
+       TEST_RR(  op"add16      r14, r",12,HH2,", r",10,HH1,"") \
+       TEST_RR(  op"asx        r0, r",0,  HH1,", r",1, HH2,"") \
+       TEST_RR(  op"asx        r14, r",12,HH2,", r",10,HH1,"") \
+       TEST_RR(  op"sax        r0, r",0,  HH1,", r",1, HH2,"") \
+       TEST_RR(  op"sax        r14, r",12,HH2,", r",10,HH1,"") \
+       TEST_RR(  op"sub16      r0, r",0,  HH1,", r",1, HH2,"") \
+       TEST_RR(  op"sub16      r14, r",12,HH2,", r",10,HH1,"") \
+       TEST_RR(  op"add8       r0, r",0,  HH1,", r",1, HH2,"") \
+       TEST_RR(  op"add8       r14, r",12,HH2,", r",10,HH1,"") \
+       TEST_RR(  op"sub8       r0, r",0,  HH1,", r",1, HH2,"") \
+       TEST_RR(  op"sub8       r14, r",12,HH2,", r",10,HH1,"")
+
+       TEST_GROUP("Parallel addition and subtraction, signed")
+
+       PARALLEL_ADD_SUB("s")
+       PARALLEL_ADD_SUB("q")
+       PARALLEL_ADD_SUB("sh")
+
+       TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+       PARALLEL_ADD_SUB("u")
+       PARALLEL_ADD_SUB("uq")
+       PARALLEL_ADD_SUB("uh")
+
+       TEST_GROUP("Miscellaneous operations")
+
+       TEST_RR("qadd   r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR("qadd   lr, r",9, VAL2,", r",8, VAL1,"")
+       TEST_RR("qsub   r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR("qsub   lr, r",9, VAL2,", r",8, VAL1,"")
+       TEST_RR("qdadd  r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR("qdadd  lr, r",9, VAL2,", r",8, VAL1,"")
+       TEST_RR("qdsub  r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR("qdsub  lr, r",9, VAL2,", r",8, VAL1,"")
+
+       TEST_R("rev.w   r0, r",0,   VAL1,"")
+       TEST_R("rev     r14, r",12, VAL2,"")
+       TEST_R("rev16.w r0, r",0,   VAL1,"")
+       TEST_R("rev16   r14, r",12, VAL2,"")
+       TEST_R("rbit    r0, r",0,   VAL1,"")
+       TEST_R("rbit    r14, r",12, VAL2,"")
+       TEST_R("revsh.w r0, r",0,   VAL1,"")
+       TEST_R("revsh   r14, r",12, VAL2,"")
+
+       TEST_UNSUPPORTED(".short 0xfa9c,0xff8c  @ rev   pc, r12");
+       TEST_UNSUPPORTED(".short 0xfa9c,0xfd8c  @ rev   sp, r12");
+       TEST_UNSUPPORTED(".short 0xfa9f,0xfe8f  @ rev   r14, pc");
+       TEST_UNSUPPORTED(".short 0xfa9d,0xfe8d  @ rev   r14, sp");
+
+       TEST_RR("sel    r0, r",0,  VAL1,", r",1, VAL2,"")
+       TEST_RR("sel    r14, r",12,VAL1,", r",10, VAL2,"")
+
+       TEST_R("clz     r0, r",0, 0x0,"")
+       TEST_R("clz     r7, r",14,0x1,"")
+       TEST_R("clz     lr, r",7, 0xffffffff,"")
+
+       TEST_UNSUPPORTED(".short 0xfa80,0xf030") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xfab0,0xf000") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+
+       TEST_GROUP("Multiply, multiply accumulate, and absolute difference operations")
+
+       TEST_RR(    "mul        r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "mul        r7, r",8, VAL2,", r",9, VAL2,"")
+       TEST_UNSUPPORTED(".short 0xfb08,0xff09  @ mul   pc, r8, r9")
+       TEST_UNSUPPORTED(".short 0xfb08,0xfd09  @ mul   sp, r8, r9")
+       TEST_UNSUPPORTED(".short 0xfb0f,0xf709  @ mul   r7, pc, r9")
+       TEST_UNSUPPORTED(".short 0xfb0d,0xf709  @ mul   r7, sp, r9")
+       TEST_UNSUPPORTED(".short 0xfb08,0xf70f  @ mul   r7, r8, pc")
+       TEST_UNSUPPORTED(".short 0xfb08,0xf70d  @ mul   r7, r8, sp")
+
+       TEST_RRR(   "mla        r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(   "mla        r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_UNSUPPORTED(".short 0xfb08,0xaf09  @ mla   pc, r8, r9, r10");
+       TEST_UNSUPPORTED(".short 0xfb08,0xad09  @ mla   sp, r8, r9, r10");
+       TEST_UNSUPPORTED(".short 0xfb0f,0xa709  @ mla   r7, pc, r9, r10");
+       TEST_UNSUPPORTED(".short 0xfb0d,0xa709  @ mla   r7, sp, r9, r10");
+       TEST_UNSUPPORTED(".short 0xfb08,0xa70f  @ mla   r7, r8, pc, r10");
+       TEST_UNSUPPORTED(".short 0xfb08,0xa70d  @ mla   r7, r8, sp, r10");
+       TEST_UNSUPPORTED(".short 0xfb08,0xd709  @ mla   r7, r8, r9, sp");
+
+       TEST_RRR(   "mls        r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(   "mls        r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+
+       TEST_RRR(   "smlabb     r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(   "smlabb     r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RRR(   "smlatb     r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(   "smlatb     r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RRR(   "smlabt     r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(   "smlabt     r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RRR(   "smlatt     r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(   "smlatt     r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(    "smulbb     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulbb     r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_RR(    "smultb     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smultb     r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_RR(    "smulbt     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulbt     r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_RR(    "smultt     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smultt     r7, r",8, VAL3,", r",9, VAL1,"")
+
+       TEST_RRR(   "smlad      r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+       TEST_RRR(   "smlad      r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+       TEST_RRR(   "smladx     r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+       TEST_RRR(   "smladx     r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+       TEST_RR(    "smuad      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "smuad      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_RR(    "smuadx     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "smuadx     r14, r",12,HH2,", r",10,HH1,"")
+
+       TEST_RRR(   "smlawb     r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(   "smlawb     r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RRR(   "smlawt     r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+       TEST_RRR(   "smlawt     r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+       TEST_RR(    "smulwb     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulwb     r7, r",8, VAL3,", r",9, VAL1,"")
+       TEST_RR(    "smulwt     r0, r",1, VAL1,", r",2, VAL2,"")
+       TEST_RR(    "smulwt     r7, r",8, VAL3,", r",9, VAL1,"")
+
+       TEST_RRR(   "smlsd      r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+       TEST_RRR(   "smlsd      r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+       TEST_RRR(   "smlsdx     r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+       TEST_RRR(   "smlsdx     r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+       TEST_RR(    "smusd      r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "smusd      r14, r",12,HH2,", r",10,HH1,"")
+       TEST_RR(    "smusdx     r0, r",0,  HH1,", r",1, HH2,"")
+       TEST_RR(    "smusdx     r14, r",12,HH2,", r",10,HH1,"")
+
+       TEST_RRR(   "smmla      r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+       TEST_RRR(   "smmla      r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+       TEST_RRR(   "smmlar     r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+       TEST_RRR(   "smmlar     r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+       TEST_RR(    "smmul      r0, r",0,  VAL1,", r",1, VAL2,"")
+       TEST_RR(    "smmul      r14, r",12,VAL2,", r",10,VAL1,"")
+       TEST_RR(    "smmulr     r0, r",0,  VAL1,", r",1, VAL2,"")
+       TEST_RR(    "smmulr     r14, r",12,VAL2,", r",10,VAL1,"")
+
+       TEST_RRR(   "smmls      r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+       TEST_RRR(   "smmls      r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+       TEST_RRR(   "smmlsr     r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+       TEST_RRR(   "smmlsr     r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+
+       TEST_RRR(   "usada8     r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL3,"")
+       TEST_RRR(   "usada8     r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+       TEST_RR(    "usad8      r0, r",0,  VAL1,", r",1, VAL2,"")
+       TEST_RR(    "usad8      r14, r",12,VAL2,", r",10,VAL1,"")
+
+       TEST_UNSUPPORTED(".short 0xfb00,0xf010") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xfb0f,0xff1f") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xfb70,0xf010") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xfb70,0x0010") /* Unallocated space */
+       TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+
+       TEST_GROUP("Long multiply, long multiply accumulate, and divide")
+
+       TEST_RR(   "smull       r0, r1, r",2, VAL1,", r",3, VAL2,"")
+       TEST_RR(   "smull       r7, r8, r",9, VAL2,", r",10, VAL1,"")
+       TEST_UNSUPPORTED(".short 0xfb89,0xf80a  @ smull pc, r8, r9, r10");
+       TEST_UNSUPPORTED(".short 0xfb89,0xd80a  @ smull sp, r8, r9, r10");
+       TEST_UNSUPPORTED(".short 0xfb89,0x7f0a  @ smull r7, pc, r9, r10");
+       TEST_UNSUPPORTED(".short 0xfb89,0x7d0a  @ smull r7, sp, r9, r10");
+       TEST_UNSUPPORTED(".short 0xfb8f,0x780a  @ smull r7, r8, pc, r10");
+       TEST_UNSUPPORTED(".short 0xfb8d,0x780a  @ smull r7, r8, sp, r10");
+       TEST_UNSUPPORTED(".short 0xfb89,0x780f  @ smull r7, r8, r9, pc");
+       TEST_UNSUPPORTED(".short 0xfb89,0x780d  @ smull r7, r8, r9, sp");
+
+       TEST_RR(   "umull       r0, r1, r",2, VAL1,", r",3, VAL2,"")
+       TEST_RR(   "umull       r7, r8, r",9, VAL2,", r",10, VAL1,"")
+
+       TEST_RRRR( "smlal       r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR( "smlal       r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+       TEST_RRRR( "smlalbb     r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR( "smlalbb     r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRRR( "smlalbt     r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR( "smlalbt     r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRRR( "smlaltb     r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR( "smlaltb     r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRRR( "smlaltt     r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR( "smlaltt     r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+       TEST_RRRR( "smlald      r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+       TEST_RRRR( "smlald      r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+       TEST_RRRR( "smlaldx     r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+       TEST_RRRR( "smlaldx     r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+       TEST_RRRR( "smlsld      r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+       TEST_RRRR( "smlsld      r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+       TEST_RRRR( "smlsldx     r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+       TEST_RRRR( "smlsldx     r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+       TEST_RRRR( "umlal       r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR( "umlal       r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+       TEST_RRRR( "umaal       r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+       TEST_RRRR( "umaal       r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+       TEST_GROUP("Coprocessor instructions")
+
+       TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+       TEST_UNSUPPORTED(".short 0xffff,0xffff")
+
+       TEST_GROUP("Testing instructions in IT blocks")
+
+       TEST_ITBLOCK("sub.w     r0, r0")
+
+       verbose("\n");
+}
+
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
new file mode 100644 (file)
index 0000000..e17cdd6
--- /dev/null
@@ -0,0 +1,1748 @@
+/*
+ * arch/arm/kernel/kprobes-test.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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 file contains test code for ARM kprobes.
+ *
+ * The top level function run_all_tests() executes tests for all of the
+ * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests
+ * fall into two categories; run_api_tests() checks basic functionality of the
+ * kprobes API, and run_test_cases() is a comprehensive test for kprobes
+ * instruction decoding and simulation.
+ *
+ * run_test_cases() first checks the kprobes decoding table for self consistency
+ * (using table_test()) then executes a series of test cases for each of the CPU
+ * instruction forms. coverage_start() and coverage_end() are used to verify
+ * that these test cases cover all of the possible combinations of instructions
+ * described by the kprobes decoding tables.
+ *
+ * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c
+ * which use the macros defined in kprobes-test.h. The rest of this
+ * documentation will describe the operation of the framework used by these
+ * test cases.
+ */
+
+/*
+ * TESTING METHODOLOGY
+ * -------------------
+ *
+ * The methodology used to test an ARM instruction 'test_insn' is to use
+ * inline assembler like:
+ *
+ * test_before: nop
+ * test_case:  test_insn
+ * test_after: nop
+ *
+ * When the test case is run a kprobe is placed of each nop. The
+ * post-handler of the test_before probe is used to modify the saved CPU
+ * register context to that which we require for the test case. The
+ * pre-handler of the of the test_after probe saves a copy of the CPU
+ * register context. In this way we can execute test_insn with a specific
+ * register context and see the results afterwards.
+ *
+ * To actually test the kprobes instruction emulation we perform the above
+ * step a second time but with an additional kprobe on the test_case
+ * instruction itself. If the emulation is accurate then the results seen
+ * by the test_after probe will be identical to the first run which didn't
+ * have a probe on test_case.
+ *
+ * Each test case is run several times with a variety of variations in the
+ * flags value of stored in CPSR, and for Thumb code, different ITState.
+ *
+ * For instructions which can modify PC, a second test_after probe is used
+ * like this:
+ *
+ * test_before: nop
+ * test_case:  test_insn
+ * test_after: nop
+ *             b test_done
+ * test_after2: nop
+ * test_done:
+ *
+ * The test case is constructed such that test_insn branches to
+ * test_after2, or, if testing a conditional instruction, it may just
+ * continue to test_after. The probes inserted at both locations let us
+ * determine which happened. A similar approach is used for testing
+ * backwards branches...
+ *
+ *             b test_before
+ *             b test_done  @ helps to cope with off by 1 branches
+ * test_after2: nop
+ *             b test_done
+ * test_before: nop
+ * test_case:  test_insn
+ * test_after: nop
+ * test_done:
+ *
+ * The macros used to generate the assembler instructions describe above
+ * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B
+ * (branch backwards). In these, the local variables numbered 1, 50, 2 and
+ * 99 represent: test_before, test_case, test_after2 and test_done.
+ *
+ * FRAMEWORK
+ * ---------
+ *
+ * Each test case is wrapped between the pair of macros TESTCASE_START and
+ * TESTCASE_END. As well as performing the inline assembler boilerplate,
+ * these call out to the kprobes_test_case_start() and
+ * kprobes_test_case_end() functions which drive the execution of the test
+ * case. The specific arguments to use for each test case are stored as
+ * inline data constructed using the various TEST_ARG_* macros. Putting
+ * this all together, a simple test case may look like:
+ *
+ *     TESTCASE_START("Testing mov r0, r7")
+ *     TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678
+ *     TEST_ARG_END("")
+ *     TEST_INSTRUCTION("mov r0, r7")
+ *     TESTCASE_END
+ *
+ * Note, in practice the single convenience macro TEST_R would be used for this
+ * instead.
+ *
+ * The above would expand to assembler looking something like:
+ *
+ *     @ TESTCASE_START
+ *     bl      __kprobes_test_case_start
+ *     @ start of inline data...
+ *     .ascii "mov r0, r7"     @ text title for test case
+ *     .byte   0
+ *     .align  2
+ *
+ *     @ TEST_ARG_REG
+ *     .byte   ARG_TYPE_REG
+ *     .byte   7
+ *     .short  0
+ *     .word   0x1234567
+ *
+ *     @ TEST_ARG_END
+ *     .byte   ARG_TYPE_END
+ *     .byte   TEST_ISA        @ flags, including ISA being tested
+ *     .short  50f-0f          @ offset of 'test_before'
+ *     .short  2f-0f           @ offset of 'test_after2' (if relevent)
+ *     .short  99f-0f          @ offset of 'test_done'
+ *     @ start of test case code...
+ *     0:
+ *     .code   TEST_ISA        @ switch to ISA being tested
+ *
+ *     @ TEST_INSTRUCTION
+ *     50:     nop             @ location for 'test_before' probe
+ *     1:      mov r0, r7      @ the test case instruction 'test_insn'
+ *             nop             @ location for 'test_after' probe
+ *
+ *     // TESTCASE_END
+ *     2:
+ *     99:     bl __kprobes_test_case_end_##TEST_ISA
+ *     .code   NONMAL_ISA
+ *
+ * When the above is execute the following happens...
+ *
+ * __kprobes_test_case_start() is an assembler wrapper which sets up space
+ * for a stack buffer and calls the C function kprobes_test_case_start().
+ * This C function will do some initial processing of the inline data and
+ * setup some global state. It then inserts the test_before and test_after
+ * kprobes and returns a value which causes the assembler wrapper to jump
+ * to the start of the test case code, (local label '0').
+ *
+ * When the test case code executes, the test_before probe will be hit and
+ * test_before_post_handler will call setup_test_context(). This fills the
+ * stack buffer and CPU registers with a test pattern and then processes
+ * the test case arguments. In our example there is one TEST_ARG_REG which
+ * indicates that R7 should be loaded with the value 0x12345678.
+ *
+ * When the test_before probe ends, the test case continues and executes
+ * the "mov r0, r7" instruction. It then hits the test_after probe and the
+ * pre-handler for this (test_after_pre_handler) will save a copy of the
+ * CPU register context. This should now have R0 holding the same value as
+ * R7.
+ *
+ * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is
+ * an assembler wrapper which switches back to the ISA used by the test
+ * code and calls the C function kprobes_test_case_end().
+ *
+ * For each run through the test case, test_case_run_count is incremented
+ * by one. For even runs, kprobes_test_case_end() saves a copy of the
+ * register and stack buffer contents from the test case just run. It then
+ * inserts a kprobe on the test case instruction 'test_insn' and returns a
+ * value to cause the test case code to be re-run.
+ *
+ * For odd numbered runs, kprobes_test_case_end() compares the register and
+ * stack buffer contents to those that were saved on the previous even
+ * numbered run (the one without the kprobe on test_insn). These should be
+ * the same if the kprobe instruction simulation routine is correct.
+ *
+ * The pair of test case runs is repeated with different combinations of
+ * flag values in CPSR and, for Thumb, different ITState. This is
+ * controlled by test_context_cpsr().
+ *
+ * BUILDING TEST CASES
+ * -------------------
+ *
+ *
+ * As an aid to building test cases, the stack buffer is initialised with
+ * some special values:
+ *
+ *   [SP+13*4] Contains SP+120. This can be used to test instructions
+ *             which load a value into SP.
+ *
+ *   [SP+15*4] When testing branching instructions using TEST_BRANCH_{F,B},
+ *             this holds the target address of the branch, 'test_after2'.
+ *             This can be used to test instructions which load a PC value
+ *             from memory.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+#include "kprobes-test.h"
+
+
+#define BENCHMARKING   1
+
+
+/*
+ * Test basic API
+ */
+
+static bool test_regs_ok;
+static int test_func_instance;
+static int pre_handler_called;
+static int post_handler_called;
+static int jprobe_func_called;
+static int kretprobe_handler_called;
+
+#define FUNC_ARG1 0x12345678
+#define FUNC_ARG2 0xabcdef
+
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+long arm_func(long r0, long r1);
+
+static void __used __naked __arm_kprobes_test_func(void)
+{
+       __asm__ __volatile__ (
+               ".arm                                   \n\t"
+               ".type arm_func, %%function             \n\t"
+               "arm_func:                              \n\t"
+               "adds   r0, r0, r1                      \n\t"
+               "bx     lr                              \n\t"
+               ".code "NORMAL_ISA       /* Back to Thumb if necessary */
+               : : : "r0", "r1", "cc"
+       );
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+long thumb16_func(long r0, long r1);
+long thumb32even_func(long r0, long r1);
+long thumb32odd_func(long r0, long r1);
+
+static void __used __naked __thumb_kprobes_test_funcs(void)
+{
+       __asm__ __volatile__ (
+               ".type thumb16_func, %%function         \n\t"
+               "thumb16_func:                          \n\t"
+               "adds.n r0, r0, r1                      \n\t"
+               "bx     lr                              \n\t"
+
+               ".align                                 \n\t"
+               ".type thumb32even_func, %%function     \n\t"
+               "thumb32even_func:                      \n\t"
+               "adds.w r0, r0, r1                      \n\t"
+               "bx     lr                              \n\t"
+
+               ".align                                 \n\t"
+               "nop.n                                  \n\t"
+               ".type thumb32odd_func, %%function      \n\t"
+               "thumb32odd_func:                       \n\t"
+               "adds.w r0, r0, r1                      \n\t"
+               "bx     lr                              \n\t"
+
+               : : : "r0", "r1", "cc"
+       );
+}
+
+#endif /* CONFIG_THUMB2_KERNEL */
+
+
+static int call_test_func(long (*func)(long, long), bool check_test_regs)
+{
+       long ret;
+
+       ++test_func_instance;
+       test_regs_ok = false;
+
+       ret = (*func)(FUNC_ARG1, FUNC_ARG2);
+       if (ret != FUNC_ARG1 + FUNC_ARG2) {
+               pr_err("FAIL: call_test_func: func returned %lx\n", ret);
+               return false;
+       }
+
+       if (check_test_regs && !test_regs_ok) {
+               pr_err("FAIL: test regs not OK\n");
+               return false;
+       }
+
+       return true;
+}
+
+static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       pre_handler_called = test_func_instance;
+       if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2)
+               test_regs_ok = true;
+       return 0;
+}
+
+static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs,
+                               unsigned long flags)
+{
+       post_handler_called = test_func_instance;
+       if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2)
+               test_regs_ok = false;
+}
+
+static struct kprobe the_kprobe = {
+       .addr           = 0,
+       .pre_handler    = pre_handler,
+       .post_handler   = post_handler
+};
+
+static int test_kprobe(long (*func)(long, long))
+{
+       int ret;
+
+       the_kprobe.addr = (kprobe_opcode_t *)func;
+       ret = register_kprobe(&the_kprobe);
+       if (ret < 0) {
+               pr_err("FAIL: register_kprobe failed with %d\n", ret);
+               return ret;
+       }
+
+       ret = call_test_func(func, true);
+
+       unregister_kprobe(&the_kprobe);
+       the_kprobe.flags = 0; /* Clear disable flag to allow reuse */
+
+       if (!ret)
+               return -EINVAL;
+       if (pre_handler_called != test_func_instance) {
+               pr_err("FAIL: kprobe pre_handler not called\n");
+               return -EINVAL;
+       }
+       if (post_handler_called != test_func_instance) {
+               pr_err("FAIL: kprobe post_handler not called\n");
+               return -EINVAL;
+       }
+       if (!call_test_func(func, false))
+               return -EINVAL;
+       if (pre_handler_called == test_func_instance ||
+                               post_handler_called == test_func_instance) {
+               pr_err("FAIL: probe called after unregistering\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void __kprobes jprobe_func(long r0, long r1)
+{
+       jprobe_func_called = test_func_instance;
+       if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2)
+               test_regs_ok = true;
+       jprobe_return();
+}
+
+static struct jprobe the_jprobe = {
+       .entry          = jprobe_func,
+};
+
+static int test_jprobe(long (*func)(long, long))
+{
+       int ret;
+
+       the_jprobe.kp.addr = (kprobe_opcode_t *)func;
+       ret = register_jprobe(&the_jprobe);
+       if (ret < 0) {
+               pr_err("FAIL: register_jprobe failed with %d\n", ret);
+               return ret;
+       }
+
+       ret = call_test_func(func, true);
+
+       unregister_jprobe(&the_jprobe);
+       the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+       if (!ret)
+               return -EINVAL;
+       if (jprobe_func_called != test_func_instance) {
+               pr_err("FAIL: jprobe handler function not called\n");
+               return -EINVAL;
+       }
+       if (!call_test_func(func, false))
+               return -EINVAL;
+       if (jprobe_func_called == test_func_instance) {
+               pr_err("FAIL: probe called after unregistering\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int __kprobes
+kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+       kretprobe_handler_called = test_func_instance;
+       if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2)
+               test_regs_ok = true;
+       return 0;
+}
+
+static struct kretprobe the_kretprobe = {
+       .handler        = kretprobe_handler,
+};
+
+static int test_kretprobe(long (*func)(long, long))
+{
+       int ret;
+
+       the_kretprobe.kp.addr = (kprobe_opcode_t *)func;
+       ret = register_kretprobe(&the_kretprobe);
+       if (ret < 0) {
+               pr_err("FAIL: register_kretprobe failed with %d\n", ret);
+               return ret;
+       }
+
+       ret = call_test_func(func, true);
+
+       unregister_kretprobe(&the_kretprobe);
+       the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+       if (!ret)
+               return -EINVAL;
+       if (kretprobe_handler_called != test_func_instance) {
+               pr_err("FAIL: kretprobe handler not called\n");
+               return -EINVAL;
+       }
+       if (!call_test_func(func, false))
+               return -EINVAL;
+       if (jprobe_func_called == test_func_instance) {
+               pr_err("FAIL: kretprobe called after unregistering\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int run_api_tests(long (*func)(long, long))
+{
+       int ret;
+
+       pr_info("    kprobe\n");
+       ret = test_kprobe(func);
+       if (ret < 0)
+               return ret;
+
+       pr_info("    jprobe\n");
+       ret = test_jprobe(func);
+       if (ret < 0)
+               return ret;
+
+       pr_info("    kretprobe\n");
+       ret = test_kretprobe(func);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+
+/*
+ * Benchmarking
+ */
+
+#if BENCHMARKING
+
+static void __naked benchmark_nop(void)
+{
+       __asm__ __volatile__ (
+               "nop            \n\t"
+               "bx     lr"
+       );
+}
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define wide ".w"
+#else
+#define wide
+#endif
+
+static void __naked benchmark_pushpop1(void)
+{
+       __asm__ __volatile__ (
+               "stmdb"wide"    sp!, {r3-r11,lr}  \n\t"
+               "ldmia"wide"    sp!, {r3-r11,pc}"
+       );
+}
+
+static void __naked benchmark_pushpop2(void)
+{
+       __asm__ __volatile__ (
+               "stmdb"wide"    sp!, {r0-r8,lr}  \n\t"
+               "ldmia"wide"    sp!, {r0-r8,pc}"
+       );
+}
+
+static void __naked benchmark_pushpop3(void)
+{
+       __asm__ __volatile__ (
+               "stmdb"wide"    sp!, {r4,lr}  \n\t"
+               "ldmia"wide"    sp!, {r4,pc}"
+       );
+}
+
+static void __naked benchmark_pushpop4(void)
+{
+       __asm__ __volatile__ (
+               "stmdb"wide"    sp!, {r0,lr}  \n\t"
+               "ldmia"wide"    sp!, {r0,pc}"
+       );
+}
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+static void __naked benchmark_pushpop_thumb(void)
+{
+       __asm__ __volatile__ (
+               "push.n {r0-r7,lr}  \n\t"
+               "pop.n  {r0-r7,pc}"
+       );
+}
+
+#endif
+
+static int __kprobes
+benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       return 0;
+}
+
+static int benchmark(void(*fn)(void))
+{
+       unsigned n, i, t, t0;
+
+       for (n = 1000; ; n *= 2) {
+               t0 = sched_clock();
+               for (i = n; i > 0; --i)
+                       fn();
+               t = sched_clock() - t0;
+               if (t >= 250000000)
+                       break; /* Stop once we took more than 0.25 seconds */
+       }
+       return t / n; /* Time for one iteration in nanoseconds */
+};
+
+static int kprobe_benchmark(void(*fn)(void), unsigned offset)
+{
+       struct kprobe k = {
+               .addr           = (kprobe_opcode_t *)((uintptr_t)fn + offset),
+               .pre_handler    = benchmark_pre_handler,
+       };
+
+       int ret = register_kprobe(&k);
+       if (ret < 0) {
+               pr_err("FAIL: register_kprobe failed with %d\n", ret);
+               return ret;
+       }
+
+       ret = benchmark(fn);
+
+       unregister_kprobe(&k);
+       return ret;
+};
+
+struct benchmarks {
+       void            (*fn)(void);
+       unsigned        offset;
+       const char      *title;
+};
+
+static int run_benchmarks(void)
+{
+       int ret;
+       struct benchmarks list[] = {
+               {&benchmark_nop, 0, "nop"},
+               /*
+                * benchmark_pushpop{1,3} will have the optimised
+                * instruction emulation, whilst benchmark_pushpop{2,4} will
+                * be the equivalent unoptimised instructions.
+                */
+               {&benchmark_pushpop1, 0, "stmdb sp!, {r3-r11,lr}"},
+               {&benchmark_pushpop1, 4, "ldmia sp!, {r3-r11,pc}"},
+               {&benchmark_pushpop2, 0, "stmdb sp!, {r0-r8,lr}"},
+               {&benchmark_pushpop2, 4, "ldmia sp!, {r0-r8,pc}"},
+               {&benchmark_pushpop3, 0, "stmdb sp!, {r4,lr}"},
+               {&benchmark_pushpop3, 4, "ldmia sp!, {r4,pc}"},
+               {&benchmark_pushpop4, 0, "stmdb sp!, {r0,lr}"},
+               {&benchmark_pushpop4, 4, "ldmia sp!, {r0,pc}"},
+#ifdef CONFIG_THUMB2_KERNEL
+               {&benchmark_pushpop_thumb, 0, "push.n   {r0-r7,lr}"},
+               {&benchmark_pushpop_thumb, 2, "pop.n    {r0-r7,pc}"},
+#endif
+               {0}
+       };
+
+       struct benchmarks *b;
+       for (b = list; b->fn; ++b) {
+               ret = kprobe_benchmark(b->fn, b->offset);
+               if (ret < 0)
+                       return ret;
+               pr_info("    %dns for kprobe %s\n", ret, b->title);
+       }
+
+       pr_info("\n");
+       return 0;
+}
+
+#endif /* BENCHMARKING */
+
+
+/*
+ * Decoding table self-consistency tests
+ */
+
+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
+       [DECODE_TYPE_TABLE]     = sizeof(struct decode_table),
+       [DECODE_TYPE_CUSTOM]    = sizeof(struct decode_custom),
+       [DECODE_TYPE_SIMULATE]  = sizeof(struct decode_simulate),
+       [DECODE_TYPE_EMULATE]   = sizeof(struct decode_emulate),
+       [DECODE_TYPE_OR]        = sizeof(struct decode_or),
+       [DECODE_TYPE_REJECT]    = sizeof(struct decode_reject)
+};
+
+static int table_iter(const union decode_item *table,
+                       int (*fn)(const struct decode_header *, void *),
+                       void *args)
+{
+       const struct decode_header *h = (struct decode_header *)table;
+       int result;
+
+       for (;;) {
+               enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+               if (type == DECODE_TYPE_END)
+                       return 0;
+
+               result = fn(h, args);
+               if (result)
+                       return result;
+
+               h = (struct decode_header *)
+                       ((uintptr_t)h + decode_struct_sizes[type]);
+
+       }
+}
+
+static int table_test_fail(const struct decode_header *h, const char* message)
+{
+
+       pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n",
+                                       message, h->mask.bits, h->value.bits);
+       return -EINVAL;
+}
+
+struct table_test_args {
+       const union decode_item *root_table;
+       u32                     parent_mask;
+       u32                     parent_value;
+};
+
+static int table_test_fn(const struct decode_header *h, void *args)
+{
+       struct table_test_args *a = (struct table_test_args *)args;
+       enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+       if (h->value.bits & ~h->mask.bits)
+               return table_test_fail(h, "Match value has bits not in mask");
+
+       if ((h->mask.bits & a->parent_mask) != a->parent_mask)
+               return table_test_fail(h, "Mask has bits not in parent mask");
+
+       if ((h->value.bits ^ a->parent_value) & a->parent_mask)
+               return table_test_fail(h, "Value is inconsistent with parent");
+
+       if (type == DECODE_TYPE_TABLE) {
+               struct decode_table *d = (struct decode_table *)h;
+               struct table_test_args args2 = *a;
+               args2.parent_mask = h->mask.bits;
+               args2.parent_value = h->value.bits;
+               return table_iter(d->table.table, table_test_fn, &args2);
+       }
+
+       return 0;
+}
+
+static int table_test(const union decode_item *table)
+{
+       struct table_test_args args = {
+               .root_table     = table,
+               .parent_mask    = 0,
+               .parent_value   = 0
+       };
+       return table_iter(args.root_table, table_test_fn, &args);
+}
+
+
+/*
+ * Decoding table test coverage analysis
+ *
+ * coverage_start() builds a coverage_table which contains a list of
+ * coverage_entry's to match each entry in the specified kprobes instruction
+ * decoding table.
+ *
+ * When test cases are run, coverage_add() is called to process each case.
+ * This looks up the corresponding entry in the coverage_table and sets it as
+ * being matched, as well as clearing the regs flag appropriate for the test.
+ *
+ * After all test cases have been run, coverage_end() is called to check that
+ * all entries in coverage_table have been matched and that all regs flags are
+ * cleared. I.e. that all possible combinations of instructions described by
+ * the kprobes decoding tables have had a test case executed for them.
+ */
+
+bool coverage_fail;
+
+#define MAX_COVERAGE_ENTRIES 256
+
+struct coverage_entry {
+       const struct decode_header      *header;
+       unsigned                        regs;
+       unsigned                        nesting;
+       char                            matched;
+};
+
+struct coverage_table {
+       struct coverage_entry   *base;
+       unsigned                num_entries;
+       unsigned                nesting;
+};
+
+struct coverage_table coverage;
+
+#define COVERAGE_ANY_REG       (1<<0)
+#define COVERAGE_SP            (1<<1)
+#define COVERAGE_PC            (1<<2)
+#define COVERAGE_PCWB          (1<<3)
+
+static const char coverage_register_lookup[16] = {
+       [REG_TYPE_ANY]          = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+       [REG_TYPE_SAMEAS16]     = COVERAGE_ANY_REG,
+       [REG_TYPE_SP]           = COVERAGE_SP,
+       [REG_TYPE_PC]           = COVERAGE_PC,
+       [REG_TYPE_NOSP]         = COVERAGE_ANY_REG | COVERAGE_SP,
+       [REG_TYPE_NOSPPC]       = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+       [REG_TYPE_NOPC]         = COVERAGE_ANY_REG | COVERAGE_PC,
+       [REG_TYPE_NOPCWB]       = COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB,
+       [REG_TYPE_NOPCX]        = COVERAGE_ANY_REG,
+       [REG_TYPE_NOSPPCX]      = COVERAGE_ANY_REG | COVERAGE_SP,
+};
+
+unsigned coverage_start_registers(const struct decode_header *h)
+{
+       unsigned regs = 0;
+       int i;
+       for (i = 0; i < 20; i += 4) {
+               int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf;
+               regs |= coverage_register_lookup[r] << i;
+       }
+       return regs;
+}
+
+static int coverage_start_fn(const struct decode_header *h, void *args)
+{
+       struct coverage_table *coverage = (struct coverage_table *)args;
+       enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+       struct coverage_entry *entry = coverage->base + coverage->num_entries;
+
+       if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) {
+               pr_err("FAIL: Out of space for test coverage data");
+               return -ENOMEM;
+       }
+
+       ++coverage->num_entries;
+
+       entry->header = h;
+       entry->regs = coverage_start_registers(h);
+       entry->nesting = coverage->nesting;
+       entry->matched = false;
+
+       if (type == DECODE_TYPE_TABLE) {
+               struct decode_table *d = (struct decode_table *)h;
+               int ret;
+               ++coverage->nesting;
+               ret = table_iter(d->table.table, coverage_start_fn, coverage);
+               --coverage->nesting;
+               return ret;
+       }
+
+       return 0;
+}
+
+static int coverage_start(const union decode_item *table)
+{
+       coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *
+                               sizeof(struct coverage_entry), GFP_KERNEL);
+       coverage.num_entries = 0;
+       coverage.nesting = 0;
+       return table_iter(table, coverage_start_fn, &coverage);
+}
+
+static void
+coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn)
+{
+       int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS;
+       int i;
+       for (i = 0; i < 20; i += 4) {
+               enum decode_reg_type reg_type = (regs >> i) & 0xf;
+               int reg = (insn >> i) & 0xf;
+               int flag;
+
+               if (!reg_type)
+                       continue;
+
+               if (reg == 13)
+                       flag = COVERAGE_SP;
+               else if (reg == 15)
+                       flag = COVERAGE_PC;
+               else
+                       flag = COVERAGE_ANY_REG;
+               entry->regs &= ~(flag << i);
+
+               switch (reg_type) {
+
+               case REG_TYPE_NONE:
+               case REG_TYPE_ANY:
+               case REG_TYPE_SAMEAS16:
+                       break;
+
+               case REG_TYPE_SP:
+                       if (reg != 13)
+                               return;
+                       break;
+
+               case REG_TYPE_PC:
+                       if (reg != 15)
+                               return;
+                       break;
+
+               case REG_TYPE_NOSP:
+                       if (reg == 13)
+                               return;
+                       break;
+
+               case REG_TYPE_NOSPPC:
+               case REG_TYPE_NOSPPCX:
+                       if (reg == 13 || reg == 15)
+                               return;
+                       break;
+
+               case REG_TYPE_NOPCWB:
+                       if (!is_writeback(insn))
+                               break;
+                       if (reg == 15) {
+                               entry->regs &= ~(COVERAGE_PCWB << i);
+                               return;
+                       }
+                       break;
+
+               case REG_TYPE_NOPC:
+               case REG_TYPE_NOPCX:
+                       if (reg == 15)
+                               return;
+                       break;
+               }
+
+       }
+}
+
+static void coverage_add(kprobe_opcode_t insn)
+{
+       struct coverage_entry *entry = coverage.base;
+       struct coverage_entry *end = coverage.base + coverage.num_entries;
+       bool matched = false;
+       unsigned nesting = 0;
+
+       for (; entry < end; ++entry) {
+               const struct decode_header *h = entry->header;
+               enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+               if (entry->nesting > nesting)
+                       continue; /* Skip sub-table we didn't match */
+
+               if (entry->nesting < nesting)
+                       break; /* End of sub-table we were scanning */
+
+               if (!matched) {
+                       if ((insn & h->mask.bits) != h->value.bits)
+                               continue;
+                       entry->matched = true;
+               }
+
+               switch (type) {
+
+               case DECODE_TYPE_TABLE:
+                       ++nesting;
+                       break;
+
+               case DECODE_TYPE_CUSTOM:
+               case DECODE_TYPE_SIMULATE:
+               case DECODE_TYPE_EMULATE:
+                       coverage_add_registers(entry, insn);
+                       return;
+
+               case DECODE_TYPE_OR:
+                       matched = true;
+                       break;
+
+               case DECODE_TYPE_REJECT:
+               default:
+                       return;
+               }
+
+       }
+}
+
+static void coverage_end(void)
+{
+       struct coverage_entry *entry = coverage.base;
+       struct coverage_entry *end = coverage.base + coverage.num_entries;
+
+       for (; entry < end; ++entry) {
+               u32 mask = entry->header->mask.bits;
+               u32 value = entry->header->value.bits;
+
+               if (entry->regs) {
+                       pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n",
+                               mask, value, entry->regs);
+                       coverage_fail = true;
+               }
+               if (!entry->matched) {
+                       pr_err("FAIL: Test coverage entry missing for %08x %08x\n",
+                               mask, value);
+                       coverage_fail = true;
+               }
+       }
+
+       kfree(coverage.base);
+}
+
+
+/*
+ * Framework for instruction set test cases
+ */
+
+void __naked __kprobes_test_case_start(void)
+{
+       __asm__ __volatile__ (
+               "stmdb  sp!, {r4-r11}                           \n\t"
+               "sub    sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+               "bic    r0, lr, #1  @ r0 = inline title string  \n\t"
+               "mov    r1, sp                                  \n\t"
+               "bl     kprobes_test_case_start                 \n\t"
+               "bx     r0                                      \n\t"
+       );
+}
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+void __naked __kprobes_test_case_end_32(void)
+{
+       __asm__ __volatile__ (
+               "mov    r4, lr                                  \n\t"
+               "bl     kprobes_test_case_end                   \n\t"
+               "cmp    r0, #0                                  \n\t"
+               "movne  pc, r0                                  \n\t"
+               "mov    r0, r4                                  \n\t"
+               "add    sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+               "ldmia  sp!, {r4-r11}                           \n\t"
+               "mov    pc, r0                                  \n\t"
+       );
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+void __naked __kprobes_test_case_end_16(void)
+{
+       __asm__ __volatile__ (
+               "mov    r4, lr                                  \n\t"
+               "bl     kprobes_test_case_end                   \n\t"
+               "cmp    r0, #0                                  \n\t"
+               "bxne   r0                                      \n\t"
+               "mov    r0, r4                                  \n\t"
+               "add    sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+               "ldmia  sp!, {r4-r11}                           \n\t"
+               "bx     r0                                      \n\t"
+       );
+}
+
+void __naked __kprobes_test_case_end_32(void)
+{
+       __asm__ __volatile__ (
+               ".arm                                           \n\t"
+               "orr    lr, lr, #1  @ will return to Thumb code \n\t"
+               "ldr    pc, 1f                                  \n\t"
+               "1:                                             \n\t"
+               ".word  __kprobes_test_case_end_16              \n\t"
+       );
+}
+
+#endif
+
+
+int kprobe_test_flags;
+int kprobe_test_cc_position;
+
+static int test_try_count;
+static int test_pass_count;
+static int test_fail_count;
+
+static struct pt_regs initial_regs;
+static struct pt_regs expected_regs;
+static struct pt_regs result_regs;
+
+static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)];
+
+static const char *current_title;
+static struct test_arg *current_args;
+static u32 *current_stack;
+static uintptr_t current_branch_target;
+
+static uintptr_t current_code_start;
+static kprobe_opcode_t current_instruction;
+
+
+#define TEST_CASE_PASSED -1
+#define TEST_CASE_FAILED -2
+
+static int test_case_run_count;
+static bool test_case_is_thumb;
+static int test_instance;
+
+/*
+ * We ignore the state of the imprecise abort disable flag (CPSR.A) because this
+ * can change randomly as the kernel doesn't take care to preserve or initialise
+ * this across context switches. Also, with Security Extentions, the flag may
+ * not be under control of the kernel; for this reason we ignore the state of
+ * the FIQ disable flag CPSR.F as well.
+ */
+#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
+
+static unsigned long test_check_cc(int cc, unsigned long cpsr)
+{
+       unsigned long temp;
+
+       switch (cc) {
+       case 0x0: /* eq */
+               return cpsr & PSR_Z_BIT;
+
+       case 0x1: /* ne */
+               return (~cpsr) & PSR_Z_BIT;
+
+       case 0x2: /* cs */
+               return cpsr & PSR_C_BIT;
+
+       case 0x3: /* cc */
+               return (~cpsr) & PSR_C_BIT;
+
+       case 0x4: /* mi */
+               return cpsr & PSR_N_BIT;
+
+       case 0x5: /* pl */
+               return (~cpsr) & PSR_N_BIT;
+
+       case 0x6: /* vs */
+               return cpsr & PSR_V_BIT;
+
+       case 0x7: /* vc */
+               return (~cpsr) & PSR_V_BIT;
+
+       case 0x8: /* hi */
+               cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+               return cpsr & PSR_C_BIT;
+
+       case 0x9: /* ls */
+               cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+               return (~cpsr) & PSR_C_BIT;
+
+       case 0xa: /* ge */
+               cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+               return (~cpsr) & PSR_N_BIT;
+
+       case 0xb: /* lt */
+               cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+               return cpsr & PSR_N_BIT;
+
+       case 0xc: /* gt */
+               temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+               temp |= (cpsr << 1);       /* PSR_N_BIT |= PSR_Z_BIT */
+               return (~temp) & PSR_N_BIT;
+
+       case 0xd: /* le */
+               temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+               temp |= (cpsr << 1);       /* PSR_N_BIT |= PSR_Z_BIT */
+               return temp & PSR_N_BIT;
+
+       case 0xe: /* al */
+       case 0xf: /* unconditional */
+               return true;
+       }
+       BUG();
+       return false;
+}
+
+static int is_last_scenario;
+static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */
+static int memory_needs_checking;
+
+static unsigned long test_context_cpsr(int scenario)
+{
+       unsigned long cpsr;
+
+       probe_should_run = 1;
+
+       /* Default case is that we cycle through 16 combinations of flags */
+       cpsr  = (scenario & 0xf) << 28; /* N,Z,C,V flags */
+       cpsr |= (scenario & 0xf) << 16; /* GE flags */
+       cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */
+
+       if (!test_case_is_thumb) {
+               /* Testing ARM code */
+               probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;
+               if (scenario == 15)
+                       is_last_scenario = true;
+
+       } else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) {
+               /* Testing Thumb code without setting ITSTATE */
+               if (kprobe_test_cc_position) {
+                       int cc = (current_instruction >> kprobe_test_cc_position) & 0xf;
+                       probe_should_run = test_check_cc(cc, cpsr) != 0;
+               }
+
+               if (scenario == 15)
+                       is_last_scenario = true;
+
+       } else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) {
+               /* Testing Thumb code with all combinations of ITSTATE */
+               unsigned x = (scenario >> 4);
+               unsigned cond_base = x % 7; /* ITSTATE<7:5> */
+               unsigned mask = x / 7 + 2;  /* ITSTATE<4:0>, bits reversed */
+
+               if (mask > 0x1f) {
+                       /* Finish by testing state from instruction 'itt al' */
+                       cond_base = 7;
+                       mask = 0x4;
+                       if ((scenario & 0xf) == 0xf)
+                               is_last_scenario = true;
+               }
+
+               cpsr |= cond_base << 13;        /* ITSTATE<7:5> */
+               cpsr |= (mask & 0x1) << 12;     /* ITSTATE<4> */
+               cpsr |= (mask & 0x2) << 10;     /* ITSTATE<3> */
+               cpsr |= (mask & 0x4) << 8;      /* ITSTATE<2> */
+               cpsr |= (mask & 0x8) << 23;     /* ITSTATE<1> */
+               cpsr |= (mask & 0x10) << 21;    /* ITSTATE<0> */
+
+               probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0;
+
+       } else {
+               /* Testing Thumb code with several combinations of ITSTATE */
+               switch (scenario) {
+               case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */
+                       cpsr = 0x00000800;
+                       probe_should_run = 0;
+                       break;
+               case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */
+                       cpsr = 0xf0007800;
+                       probe_should_run = 0;
+                       break;
+               case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */
+                       cpsr = 0x00009800;
+                       break;
+               case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */
+                       cpsr = 0xf0002800;
+                       is_last_scenario = true;
+                       break;
+               }
+       }
+
+       return cpsr;
+}
+
+static void setup_test_context(struct pt_regs *regs)
+{
+       int scenario = test_case_run_count>>1;
+       unsigned long val;
+       struct test_arg *args;
+       int i;
+
+       is_last_scenario = false;
+       memory_needs_checking = false;
+
+       /* Initialise test memory on stack */
+       val = (scenario & 1) ? VALM : ~VALM;
+       for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i)
+               current_stack[i] = val + (i << 8);
+       /* Put target of branch on stack for tests which load PC from memory */
+       if (current_branch_target)
+               current_stack[15] = current_branch_target;
+       /* Put a value for SP on stack for tests which load SP from memory */
+       current_stack[13] = (u32)current_stack + 120;
+
+       /* Initialise register values to their default state */
+       val = (scenario & 2) ? VALR : ~VALR;
+       for (i = 0; i < 13; ++i)
+               regs->uregs[i] = val ^ (i << 8);
+       regs->ARM_lr = val ^ (14 << 8);
+       regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK);
+       regs->ARM_cpsr |= test_context_cpsr(scenario);
+
+       /* Perform testcase specific register setup  */
+       args = current_args;
+       for (; args[0].type != ARG_TYPE_END; ++args)
+               switch (args[0].type) {
+               case ARG_TYPE_REG: {
+                       struct test_arg_regptr *arg =
+                               (struct test_arg_regptr *)args;
+                       regs->uregs[arg->reg] = arg->val;
+                       break;
+               }
+               case ARG_TYPE_PTR: {
+                       struct test_arg_regptr *arg =
+                               (struct test_arg_regptr *)args;
+                       regs->uregs[arg->reg] =
+                               (unsigned long)current_stack + arg->val;
+                       memory_needs_checking = true;
+                       break;
+               }
+               case ARG_TYPE_MEM: {
+                       struct test_arg_mem *arg = (struct test_arg_mem *)args;
+                       current_stack[arg->index] = arg->val;
+                       break;
+               }
+               default:
+                       break;
+               }
+}
+
+struct test_probe {
+       struct kprobe   kprobe;
+       bool            registered;
+       int             hit;
+};
+
+static void unregister_test_probe(struct test_probe *probe)
+{
+       if (probe->registered) {
+               unregister_kprobe(&probe->kprobe);
+               probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */
+       }
+       probe->registered = false;
+}
+
+static int register_test_probe(struct test_probe *probe)
+{
+       int ret;
+
+       if (probe->registered)
+               BUG();
+
+       ret = register_kprobe(&probe->kprobe);
+       if (ret >= 0) {
+               probe->registered = true;
+               probe->hit = -1;
+       }
+       return ret;
+}
+
+static int __kprobes
+test_before_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       container_of(p, struct test_probe, kprobe)->hit = test_instance;
+       return 0;
+}
+
+static void __kprobes
+test_before_post_handler(struct kprobe *p, struct pt_regs *regs,
+                                                       unsigned long flags)
+{
+       setup_test_context(regs);
+       initial_regs = *regs;
+       initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+}
+
+static int __kprobes
+test_case_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       container_of(p, struct test_probe, kprobe)->hit = test_instance;
+       return 0;
+}
+
+static int __kprobes
+test_after_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       if (container_of(p, struct test_probe, kprobe)->hit == test_instance)
+               return 0; /* Already run for this test instance */
+
+       result_regs = *regs;
+       result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+
+       /* Undo any changes done to SP by the test case */
+       regs->ARM_sp = (unsigned long)current_stack;
+
+       container_of(p, struct test_probe, kprobe)->hit = test_instance;
+       return 0;
+}
+
+static struct test_probe test_before_probe = {
+       .kprobe.pre_handler     = test_before_pre_handler,
+       .kprobe.post_handler    = test_before_post_handler,
+};
+
+static struct test_probe test_case_probe = {
+       .kprobe.pre_handler     = test_case_pre_handler,
+};
+
+static struct test_probe test_after_probe = {
+       .kprobe.pre_handler     = test_after_pre_handler,
+};
+
+static struct test_probe test_after2_probe = {
+       .kprobe.pre_handler     = test_after_pre_handler,
+};
+
+static void test_case_cleanup(void)
+{
+       unregister_test_probe(&test_before_probe);
+       unregister_test_probe(&test_case_probe);
+       unregister_test_probe(&test_after_probe);
+       unregister_test_probe(&test_after2_probe);
+}
+
+static void print_registers(struct pt_regs *regs)
+{
+       pr_err("r0  %08lx | r1  %08lx | r2  %08lx | r3  %08lx\n",
+               regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
+       pr_err("r4  %08lx | r5  %08lx | r6  %08lx | r7  %08lx\n",
+               regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
+       pr_err("r8  %08lx | r9  %08lx | r10 %08lx | r11 %08lx\n",
+               regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);
+       pr_err("r12 %08lx | sp  %08lx | lr  %08lx | pc  %08lx\n",
+               regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);
+       pr_err("cpsr %08lx\n", regs->ARM_cpsr);
+}
+
+static void print_memory(u32 *mem, size_t size)
+{
+       int i;
+       for (i = 0; i < size / sizeof(u32); i += 4)
+               pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1],
+                                               mem[i+2], mem[i+3]);
+}
+
+static size_t expected_memory_size(u32 *sp)
+{
+       size_t size = sizeof(expected_memory);
+       int offset = (uintptr_t)sp - (uintptr_t)current_stack;
+       if (offset > 0)
+               size -= offset;
+       return size;
+}
+
+static void test_case_failed(const char *message)
+{
+       test_case_cleanup();
+
+       pr_err("FAIL: %s\n", message);
+       pr_err("FAIL: Test %s\n", current_title);
+       pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1);
+}
+
+static unsigned long next_instruction(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+       if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1)))
+               return pc + 2;
+       else
+#endif
+       return pc + 4;
+}
+
+static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)
+{
+       struct test_arg *args;
+       struct test_arg_end *end_arg;
+       unsigned long test_code;
+
+       args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4);
+
+       current_title = title;
+       current_args = args;
+       current_stack = stack;
+
+       ++test_try_count;
+
+       while (args->type != ARG_TYPE_END)
+               ++args;
+       end_arg = (struct test_arg_end *)args;
+
+       test_code = (unsigned long)(args + 1); /* Code starts after args */
+
+       test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB;
+       if (test_case_is_thumb)
+               test_code |= 1;
+
+       current_code_start = test_code;
+
+       current_branch_target = 0;
+       if (end_arg->branch_offset != end_arg->end_offset)
+               current_branch_target = test_code + end_arg->branch_offset;
+
+       test_code += end_arg->code_offset;
+       test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+       test_code = next_instruction(test_code);
+       test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+       if (test_case_is_thumb) {
+               u16 *p = (u16 *)(test_code & ~1);
+               current_instruction = p[0];
+               if (is_wide_instruction(current_instruction)) {
+                       current_instruction <<= 16;
+                       current_instruction |= p[1];
+               }
+       } else {
+               current_instruction = *(u32 *)test_code;
+       }
+
+       if (current_title[0] == '.')
+               verbose("%s\n", current_title);
+       else
+               verbose("%s\t@ %0*x\n", current_title,
+                                       test_case_is_thumb ? 4 : 8,
+                                       current_instruction);
+
+       test_code = next_instruction(test_code);
+       test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+       if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) {
+               if (!test_case_is_thumb ||
+                       is_wide_instruction(current_instruction)) {
+                               test_case_failed("expected 16-bit instruction");
+                               goto fail;
+               }
+       } else {
+               if (test_case_is_thumb &&
+                       !is_wide_instruction(current_instruction)) {
+                               test_case_failed("expected 32-bit instruction");
+                               goto fail;
+               }
+       }
+
+       coverage_add(current_instruction);
+
+       if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {
+               if (register_test_probe(&test_case_probe) < 0)
+                       goto pass;
+               test_case_failed("registered probe for unsupported instruction");
+               goto fail;
+       }
+
+       if (end_arg->flags & ARG_FLAG_SUPPORTED) {
+               if (register_test_probe(&test_case_probe) >= 0)
+                       goto pass;
+               test_case_failed("couldn't register probe for supported instruction");
+               goto fail;
+       }
+
+       if (register_test_probe(&test_before_probe) < 0) {
+               test_case_failed("register test_before_probe failed");
+               goto fail;
+       }
+       if (register_test_probe(&test_after_probe) < 0) {
+               test_case_failed("register test_after_probe failed");
+               goto fail;
+       }
+       if (current_branch_target) {
+               test_after2_probe.kprobe.addr =
+                               (kprobe_opcode_t *)current_branch_target;
+               if (register_test_probe(&test_after2_probe) < 0) {
+                       test_case_failed("register test_after2_probe failed");
+                       goto fail;
+               }
+       }
+
+       /* Start first run of test case */
+       test_case_run_count = 0;
+       ++test_instance;
+       return current_code_start;
+pass:
+       test_case_run_count = TEST_CASE_PASSED;
+       return (uintptr_t)test_after_probe.kprobe.addr;
+fail:
+       test_case_run_count = TEST_CASE_FAILED;
+       return (uintptr_t)test_after_probe.kprobe.addr;
+}
+
+static bool check_test_results(void)
+{
+       size_t mem_size = 0;
+       u32 *mem = 0;
+
+       if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) {
+               test_case_failed("registers differ");
+               goto fail;
+       }
+
+       if (memory_needs_checking) {
+               mem = (u32 *)result_regs.ARM_sp;
+               mem_size = expected_memory_size(mem);
+               if (memcmp(expected_memory, mem, mem_size)) {
+                       test_case_failed("test memory differs");
+                       goto fail;
+               }
+       }
+
+       return true;
+
+fail:
+       pr_err("initial_regs:\n");
+       print_registers(&initial_regs);
+       pr_err("expected_regs:\n");
+       print_registers(&expected_regs);
+       pr_err("result_regs:\n");
+       print_registers(&result_regs);
+
+       if (mem) {
+               pr_err("current_stack=%p\n", current_stack);
+               pr_err("expected_memory:\n");
+               print_memory(expected_memory, mem_size);
+               pr_err("result_memory:\n");
+               print_memory(mem, mem_size);
+       }
+
+       return false;
+}
+
+static uintptr_t __used kprobes_test_case_end(void)
+{
+       if (test_case_run_count < 0) {
+               if (test_case_run_count == TEST_CASE_PASSED)
+                       /* kprobes_test_case_start did all the needed testing */
+                       goto pass;
+               else
+                       /* kprobes_test_case_start failed */
+                       goto fail;
+       }
+
+       if (test_before_probe.hit != test_instance) {
+               test_case_failed("test_before_handler not run");
+               goto fail;
+       }
+
+       if (test_after_probe.hit != test_instance &&
+                               test_after2_probe.hit != test_instance) {
+               test_case_failed("test_after_handler not run");
+               goto fail;
+       }
+
+       /*
+        * Even numbered test runs ran without a probe on the test case so
+        * we can gather reference results. The subsequent odd numbered run
+        * will have the probe inserted.
+       */
+       if ((test_case_run_count & 1) == 0) {
+               /* Save results from run without probe */
+               u32 *mem = (u32 *)result_regs.ARM_sp;
+               expected_regs = result_regs;
+               memcpy(expected_memory, mem, expected_memory_size(mem));
+
+               /* Insert probe onto test case instruction */
+               if (register_test_probe(&test_case_probe) < 0) {
+                       test_case_failed("register test_case_probe failed");
+                       goto fail;
+               }
+       } else {
+               /* Check probe ran as expected */
+               if (probe_should_run == 1) {
+                       if (test_case_probe.hit != test_instance) {
+                               test_case_failed("test_case_handler not run");
+                               goto fail;
+                       }
+               } else if (probe_should_run == 0) {
+                       if (test_case_probe.hit == test_instance) {
+                               test_case_failed("test_case_handler ran");
+                               goto fail;
+                       }
+               }
+
+               /* Remove probe for any subsequent reference run */
+               unregister_test_probe(&test_case_probe);
+
+               if (!check_test_results())
+                       goto fail;
+
+               if (is_last_scenario)
+                       goto pass;
+       }
+
+       /* Do next test run */
+       ++test_case_run_count;
+       ++test_instance;
+       return current_code_start;
+fail:
+       ++test_fail_count;
+       goto end;
+pass:
+       ++test_pass_count;
+end:
+       test_case_cleanup();
+       return 0;
+}
+
+
+/*
+ * Top level test functions
+ */
+
+static int run_test_cases(void (*tests)(void), const union decode_item *table)
+{
+       int ret;
+
+       pr_info("    Check decoding tables\n");
+       ret = table_test(table);
+       if (ret)
+               return ret;
+
+       pr_info("    Run test cases\n");
+       ret = coverage_start(table);
+       if (ret)
+               return ret;
+
+       tests();
+
+       coverage_end();
+       return 0;
+}
+
+
+static int __init run_all_tests(void)
+{
+       int ret = 0;
+
+       pr_info("Begining kprobe tests...\n");
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+       pr_info("Probe ARM code\n");
+       ret = run_api_tests(arm_func);
+       if (ret)
+               goto out;
+
+       pr_info("ARM instruction simulation\n");
+       ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table);
+       if (ret)
+               goto out;
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+       pr_info("Probe 16-bit Thumb code\n");
+       ret = run_api_tests(thumb16_func);
+       if (ret)
+               goto out;
+
+       pr_info("Probe 32-bit Thumb code, even halfword\n");
+       ret = run_api_tests(thumb32even_func);
+       if (ret)
+               goto out;
+
+       pr_info("Probe 32-bit Thumb code, odd halfword\n");
+       ret = run_api_tests(thumb32odd_func);
+       if (ret)
+               goto out;
+
+       pr_info("16-bit Thumb instruction simulation\n");
+       ret = run_test_cases(kprobe_thumb16_test_cases,
+                               kprobe_decode_thumb16_table);
+       if (ret)
+               goto out;
+
+       pr_info("32-bit Thumb instruction simulation\n");
+       ret = run_test_cases(kprobe_thumb32_test_cases,
+                               kprobe_decode_thumb32_table);
+       if (ret)
+               goto out;
+#endif
+
+       pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n",
+               test_try_count, test_pass_count, test_fail_count);
+       if (test_fail_count) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+#if BENCHMARKING
+       pr_info("Benchmarks\n");
+       ret = run_benchmarks();
+       if (ret)
+               goto out;
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+       /* We are able to run all test cases so coverage should be complete */
+       if (coverage_fail) {
+               pr_err("FAIL: Test coverage checks failed\n");
+               ret = -EINVAL;
+               goto out;
+       }
+#endif
+
+out:
+       if (ret == 0)
+               pr_info("Finished kprobe tests OK\n");
+       else
+               pr_err("kprobe tests failed\n");
+
+       return ret;
+}
+
+
+/*
+ * Module setup
+ */
+
+#ifdef MODULE
+
+static void __exit kprobe_test_exit(void)
+{
+}
+
+module_init(run_all_tests)
+module_exit(kprobe_test_exit)
+MODULE_LICENSE("GPL");
+
+#else /* !MODULE */
+
+late_initcall(run_all_tests);
+
+#endif
diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h
new file mode 100644 (file)
index 0000000..0dc5d77
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * arch/arm/kernel/kprobes-test.h
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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.
+ */
+
+#define VERBOSE 0 /* Set to '1' for more logging of test cases */
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define NORMAL_ISA "16"
+#else
+#define NORMAL_ISA "32"
+#endif
+
+
+/* Flags used in kprobe_test_flags */
+#define TEST_FLAG_NO_ITBLOCK   (1<<0)
+#define TEST_FLAG_FULL_ITBLOCK (1<<1)
+#define TEST_FLAG_NARROW_INSTR (1<<2)
+
+extern int kprobe_test_flags;
+extern int kprobe_test_cc_position;
+
+
+#define TEST_MEMORY_SIZE 256
+
+
+/*
+ * Test case structures.
+ *
+ * The arguments given to test cases can be one of three types.
+ *
+ *   ARG_TYPE_REG
+ *     Load a register with the given value.
+ *
+ *   ARG_TYPE_PTR
+ *     Load a register with a pointer into the stack buffer (SP + given value).
+ *
+ *   ARG_TYPE_MEM
+ *     Store the given value into the stack buffer at [SP+index].
+ *
+ */
+
+#define        ARG_TYPE_END    0
+#define        ARG_TYPE_REG    1
+#define        ARG_TYPE_PTR    2
+#define        ARG_TYPE_MEM    3
+
+#define ARG_FLAG_UNSUPPORTED   0x01
+#define ARG_FLAG_SUPPORTED     0x02
+#define ARG_FLAG_THUMB         0x10    /* Must be 16 so TEST_ISA can be used */
+#define ARG_FLAG_ARM           0x20    /* Must be 32 so TEST_ISA can be used */
+
+struct test_arg {
+       u8      type;           /* ARG_TYPE_x */
+       u8      _padding[7];
+};
+
+struct test_arg_regptr {
+       u8      type;           /* ARG_TYPE_REG or ARG_TYPE_PTR */
+       u8      reg;
+       u8      _padding[2];
+       u32     val;
+};
+
+struct test_arg_mem {
+       u8      type;           /* ARG_TYPE_MEM */
+       u8      index;
+       u8      _padding[2];
+       u32     val;
+};
+
+struct test_arg_end {
+       u8      type;           /* ARG_TYPE_END */
+       u8      flags;          /* ARG_FLAG_x */
+       u16     code_offset;
+       u16     branch_offset;
+       u16     end_offset;
+};
+
+
+/*
+ * Building blocks for test cases.
+ *
+ * Each test case is wrapped between TESTCASE_START and TESTCASE_END.
+ *
+ * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are
+ * used followed by a terminating TEST_ARG_END.
+ *
+ * After this, the instruction to be tested is defined with TEST_INSTRUCTION.
+ * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards).
+ *
+ * Some specific test cases may make use of other custom constructs.
+ */
+
+#if VERBOSE
+#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__)
+#else
+#define verbose(fmt, ...)
+#endif
+
+#define TEST_GROUP(title)                                      \
+       verbose("\n");                                          \
+       verbose(title"\n");                                     \
+       verbose("---------------------------------------------------------\n");
+
+#define TESTCASE_START(title)                                  \
+       __asm__ __volatile__ (                                  \
+       "bl     __kprobes_test_case_start               \n\t"   \
+       /* don't use .asciz here as 'title' may be */           \
+       /* multiple strings to be concatenated.  */             \
+       ".ascii "#title"                                \n\t"   \
+       ".byte  0                                       \n\t"   \
+       ".align 2                                       \n\t"
+
+#define        TEST_ARG_REG(reg, val)                                  \
+       ".byte  "__stringify(ARG_TYPE_REG)"             \n\t"   \
+       ".byte  "#reg"                                  \n\t"   \
+       ".short 0                                       \n\t"   \
+       ".word  "#val"                                  \n\t"
+
+#define        TEST_ARG_PTR(reg, val)                                  \
+       ".byte  "__stringify(ARG_TYPE_PTR)"             \n\t"   \
+       ".byte  "#reg"                                  \n\t"   \
+       ".short 0                                       \n\t"   \
+       ".word  "#val"                                  \n\t"
+
+#define        TEST_ARG_MEM(index, val)                                \
+       ".byte  "__stringify(ARG_TYPE_MEM)"             \n\t"   \
+       ".byte  "#index"                                \n\t"   \
+       ".short 0                                       \n\t"   \
+       ".word  "#val"                                  \n\t"
+
+#define        TEST_ARG_END(flags)                                     \
+       ".byte  "__stringify(ARG_TYPE_END)"             \n\t"   \
+       ".byte  "TEST_ISA flags"                        \n\t"   \
+       ".short 50f-0f                                  \n\t"   \
+       ".short 2f-0f                                   \n\t"   \
+       ".short 99f-0f                                  \n\t"   \
+       ".code "TEST_ISA"                               \n\t"   \
+       "0:                                             \n\t"
+
+#define TEST_INSTRUCTION(instruction)                          \
+       "50:    nop                                     \n\t"   \
+       "1:     "instruction"                           \n\t"   \
+       "       nop                                     \n\t"
+
+#define TEST_BRANCH_F(instruction, xtra_dist)                  \
+       TEST_INSTRUCTION(instruction)                           \
+       ".if "#xtra_dist"                               \n\t"   \
+       "       b       99f                             \n\t"   \
+       ".space "#xtra_dist"                            \n\t"   \
+       ".endif                                         \n\t"   \
+       "       b       99f                             \n\t"   \
+       "2:     nop                                     \n\t"
+
+#define TEST_BRANCH_B(instruction, xtra_dist)                  \
+       "       b       50f                             \n\t"   \
+       "       b       99f                             \n\t"   \
+       "2:     nop                                     \n\t"   \
+       "       b       99f                             \n\t"   \
+       ".if "#xtra_dist"                               \n\t"   \
+       ".space "#xtra_dist"                            \n\t"   \
+       ".endif                                         \n\t"   \
+       TEST_INSTRUCTION(instruction)
+
+#define TESTCASE_END                                           \
+       "2:                                             \n\t"   \
+       "99:                                            \n\t"   \
+       "       bl __kprobes_test_case_end_"TEST_ISA"   \n\t"   \
+       ".code "NORMAL_ISA"                             \n\t"   \
+       : :                                                     \
+       : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"    \
+       );
+
+
+/*
+ * Macros to define test cases.
+ *
+ * Those of the form TEST_{R,P,M}* can be used to define test cases
+ * which take combinations of the three basic types of arguments. E.g.
+ *
+ *   TEST_R    One register argument
+ *   TEST_RR   Two register arguments
+ *   TEST_RPR  A register, a pointer, then a register argument
+ *
+ * For testing instructions which may branch, there are macros TEST_BF_*
+ * and TEST_BB_* for branching forwards and backwards.
+ *
+ * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed,
+ * the just verify that a kprobe is or is not allowed on the given instruction.
+ */
+
+#define TEST(code)                             \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       TEST_INSTRUCTION(code)                  \
+       TESTCASE_END
+
+#define TEST_UNSUPPORTED(code)                                 \
+       TESTCASE_START(code)                                    \
+       TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED))      \
+       TEST_INSTRUCTION(code)                                  \
+       TESTCASE_END
+
+#define TEST_SUPPORTED(code)                                   \
+       TESTCASE_START(code)                                    \
+       TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED))        \
+       TEST_INSTRUCTION(code)                                  \
+       TESTCASE_END
+
+#define TEST_R(code1, reg, val, code2)                 \
+       TESTCASE_START(code1 #reg code2)                \
+       TEST_ARG_REG(reg, val)                          \
+       TEST_ARG_END("")                                \
+       TEST_INSTRUCTION(code1 #reg code2)              \
+       TESTCASE_END
+
+#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3)   \
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3)           \
+       TEST_ARG_REG(reg1, val1)                                \
+       TEST_ARG_REG(reg2, val2)                                \
+       TEST_ARG_END("")                                        \
+       TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)         \
+       TESTCASE_END
+
+#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)               \
+       TEST_ARG_REG(reg1, val1)                                                \
+       TEST_ARG_REG(reg2, val2)                                                \
+       TEST_ARG_REG(reg3, val3)                                                \
+       TEST_ARG_END("")                                                        \
+       TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)             \
+       TESTCASE_END
+
+#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4)  \
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4)         \
+       TEST_ARG_REG(reg1, val1)                                                \
+       TEST_ARG_REG(reg2, val2)                                                \
+       TEST_ARG_REG(reg3, val3)                                                \
+       TEST_ARG_REG(reg4, val4)                                                \
+       TEST_ARG_END("")                                                        \
+       TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4)       \
+       TESTCASE_END
+
+#define TEST_P(code1, reg1, val1, code2)       \
+       TESTCASE_START(code1 #reg1 code2)       \
+       TEST_ARG_PTR(reg1, val1)                \
+       TEST_ARG_END("")                        \
+       TEST_INSTRUCTION(code1 #reg1 code2)     \
+       TESTCASE_END
+
+#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3)   \
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3)           \
+       TEST_ARG_PTR(reg1, val1)                                \
+       TEST_ARG_REG(reg2, val2)                                \
+       TEST_ARG_END("")                                        \
+       TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)         \
+       TESTCASE_END
+
+#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3)   \
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3)           \
+       TEST_ARG_REG(reg1, val1)                                \
+       TEST_ARG_PTR(reg2, val2)                                \
+       TEST_ARG_END("")                                        \
+       TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)         \
+       TESTCASE_END
+
+#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)               \
+       TEST_ARG_PTR(reg1, val1)                                                \
+       TEST_ARG_REG(reg2, val2)                                                \
+       TEST_ARG_REG(reg3, val3)                                                \
+       TEST_ARG_END("")                                                        \
+       TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)             \
+       TESTCASE_END
+
+#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)               \
+       TEST_ARG_REG(reg1, val1)                                                \
+       TEST_ARG_PTR(reg2, val2)                                                \
+       TEST_ARG_REG(reg3, val3)                                                \
+       TEST_ARG_END("")                                                        \
+       TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)             \
+       TESTCASE_END
+
+#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)               \
+       TEST_ARG_REG(reg1, val1)                                                \
+       TEST_ARG_REG(reg2, val2)                                                \
+       TEST_ARG_PTR(reg3, val3)                                                \
+       TEST_ARG_END("")                                                        \
+       TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)             \
+       TESTCASE_END
+
+#define TEST_BF_P(code1, reg1, val1, code2)    \
+       TESTCASE_START(code1 #reg1 code2)       \
+       TEST_ARG_PTR(reg1, val1)                \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_F(code1 #reg1 code2, 0)     \
+       TESTCASE_END
+
+#define TEST_BF_X(code, xtra_dist)             \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_F(code, xtra_dist)          \
+       TESTCASE_END
+
+#define TEST_BB_X(code, xtra_dist)             \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_B(code, xtra_dist)          \
+       TESTCASE_END
+
+#define TEST_BF_RX(code1, reg, val, code2, xtra_dist)  \
+       TESTCASE_START(code1 #reg code2)                \
+       TEST_ARG_REG(reg, val)                          \
+       TEST_ARG_END("")                                \
+       TEST_BRANCH_F(code1 #reg code2, xtra_dist)      \
+       TESTCASE_END
+
+#define TEST_BB_RX(code1, reg, val, code2, xtra_dist)  \
+       TESTCASE_START(code1 #reg code2)                \
+       TEST_ARG_REG(reg, val)                          \
+       TEST_ARG_END("")                                \
+       TEST_BRANCH_B(code1 #reg code2, xtra_dist)      \
+       TESTCASE_END
+
+#define TEST_BF(code)  TEST_BF_X(code, 0)
+#define TEST_BB(code)  TEST_BB_X(code, 0)
+
+#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0)
+#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0)
+
+#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3)        \
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3)           \
+       TEST_ARG_REG(reg1, val1)                                \
+       TEST_ARG_REG(reg2, val2)                                \
+       TEST_ARG_END("")                                        \
+       TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0)         \
+       TESTCASE_END
+
+#define TEST_X(code, codex)                    \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       TEST_INSTRUCTION(code)                  \
+       "       b       99f             \n\t"   \
+       "       "codex"                 \n\t"   \
+       TESTCASE_END
+
+#define TEST_RX(code1, reg, val, code2, codex)         \
+       TESTCASE_START(code1 #reg code2)                \
+       TEST_ARG_REG(reg, val)                          \
+       TEST_ARG_END("")                                \
+       TEST_INSTRUCTION(code1 __stringify(reg) code2)  \
+       "       b       99f             \n\t"           \
+       "       "codex"                 \n\t"           \
+       TESTCASE_END
+
+#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex)           \
+       TESTCASE_START(code1 #reg1 code2 #reg2 code3)                           \
+       TEST_ARG_REG(reg1, val1)                                                \
+       TEST_ARG_REG(reg2, val2)                                                \
+       TEST_ARG_END("")                                                        \
+       TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3) \
+       "       b       99f             \n\t"                                   \
+       "       "codex"                 \n\t"                                   \
+       TESTCASE_END
+
+
+/* Various values used in test cases... */
+#define N(val) (val ^ 0xffffffff)
+#define VAL1   0x12345678
+#define VAL2   N(VAL1)
+#define VAL3   0xa5f801
+#define VAL4   N(VAL3)
+#define VALM   0x456789ab
+#define VALR   0xdeaddead
+#define HH1    0x0123fecb
+#define HH2    0xa9874567
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+void kprobe_thumb16_test_cases(void);
+void kprobe_thumb32_test_cases(void);
+#else
+void kprobe_arm_test_cases(void);
+#endif
index 902ca59..8f96ec7 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
+#include <linux/module.h>
 
 #include "kprobes.h"
 
@@ -943,6 +944,9 @@ const union decode_item kprobe_decode_thumb32_table[] = {
         */
        DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
+#endif
 
 static void __kprobes
 t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
@@ -1423,6 +1427,9 @@ const union decode_item kprobe_decode_thumb16_table[] = {
 
        DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
+#endif
 
 static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
 {
index a6aeda0..38945f7 100644 (file)
@@ -413,6 +413,14 @@ struct decode_reject {
        DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
 
 
+#ifdef CONFIG_THUMB2_KERNEL
+extern const union decode_item kprobe_decode_thumb16_table[];
+extern const union decode_item kprobe_decode_thumb32_table[];
+#else
+extern const union decode_item kprobe_decode_arm_table[];
+#endif
+
+
 int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
                        const union decode_item *table, bool thumb16);
 
index 53c9c26..e6e5d7c 100644 (file)
@@ -12,6 +12,7 @@
  */
 #define pr_fmt(fmt) "hw perfevents: " fmt
 
+#include <linux/bitmap.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
-static struct platform_device *pmu_device;
-
-/*
- * Hardware lock to serialize accesses to PMU registers. Needed for the
- * read/modify/write sequences.
- */
-static DEFINE_RAW_SPINLOCK(pmu_lock);
-
 /*
- * ARMv6 supports a maximum of 3 events, starting from index 1. If we add
+ * ARMv6 supports a maximum of 3 events, starting from index 0. If we add
  * another platform that supports more, we need to increase this to be the
  * largest of all platforms.
  *
@@ -43,62 +36,24 @@ static DEFINE_RAW_SPINLOCK(pmu_lock);
  *  cycle counter CCNT + 31 events counters CNT0..30.
  *  Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters.
  */
-#define ARMPMU_MAX_HWEVENTS            33
+#define ARMPMU_MAX_HWEVENTS            32
 
-/* The events for a given CPU. */
-struct cpu_hw_events {
-       /*
-        * The events that are active on the CPU for the given index. Index 0
-        * is reserved.
-        */
-       struct perf_event       *events[ARMPMU_MAX_HWEVENTS];
-
-       /*
-        * A 1 bit for an index indicates that the counter is being used for
-        * an event. A 0 means that the counter can be used.
-        */
-       unsigned long           used_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
+static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
+static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
+static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
 
-       /*
-        * A 1 bit for an index indicates that the counter is actively being
-        * used.
-        */
-       unsigned long           active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
-};
-static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
-
-struct arm_pmu {
-       enum arm_perf_pmu_ids id;
-       const char      *name;
-       irqreturn_t     (*handle_irq)(int irq_num, void *dev);
-       void            (*enable)(struct hw_perf_event *evt, int idx);
-       void            (*disable)(struct hw_perf_event *evt, int idx);
-       int             (*get_event_idx)(struct cpu_hw_events *cpuc,
-                                        struct hw_perf_event *hwc);
-       u32             (*read_counter)(int idx);
-       void            (*write_counter)(int idx, u32 val);
-       void            (*start)(void);
-       void            (*stop)(void);
-       void            (*reset)(void *);
-       const unsigned  (*cache_map)[PERF_COUNT_HW_CACHE_MAX]
-                                   [PERF_COUNT_HW_CACHE_OP_MAX]
-                                   [PERF_COUNT_HW_CACHE_RESULT_MAX];
-       const unsigned  (*event_map)[PERF_COUNT_HW_MAX];
-       u32             raw_event_mask;
-       int             num_events;
-       u64             max_period;
-};
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
 
 /* Set at runtime when we know what CPU type we are. */
-static const struct arm_pmu *armpmu;
+static struct arm_pmu *cpu_pmu;
 
 enum arm_perf_pmu_ids
 armpmu_get_pmu_id(void)
 {
        int id = -ENODEV;
 
-       if (armpmu != NULL)
-               id = armpmu->id;
+       if (cpu_pmu != NULL)
+               id = cpu_pmu->id;
 
        return id;
 }
@@ -109,8 +64,8 @@ armpmu_get_max_events(void)
 {
        int max_events = 0;
 
-       if (armpmu != NULL)
-               max_events = armpmu->num_events;
+       if (cpu_pmu != NULL)
+               max_events = cpu_pmu->num_events;
 
        return max_events;
 }
@@ -130,7 +85,11 @@ EXPORT_SYMBOL_GPL(perf_num_counters);
 #define CACHE_OP_UNSUPPORTED           0xFFFF
 
 static int
-armpmu_map_cache_event(u64 config)
+armpmu_map_cache_event(const unsigned (*cache_map)
+                                     [PERF_COUNT_HW_CACHE_MAX]
+                                     [PERF_COUNT_HW_CACHE_OP_MAX]
+                                     [PERF_COUNT_HW_CACHE_RESULT_MAX],
+                      u64 config)
 {
        unsigned int cache_type, cache_op, cache_result, ret;
 
@@ -146,7 +105,7 @@ armpmu_map_cache_event(u64 config)
        if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
                return -EINVAL;
 
-       ret = (int)(*armpmu->cache_map)[cache_type][cache_op][cache_result];
+       ret = (int)(*cache_map)[cache_type][cache_op][cache_result];
 
        if (ret == CACHE_OP_UNSUPPORTED)
                return -ENOENT;
@@ -155,23 +114,46 @@ armpmu_map_cache_event(u64 config)
 }
 
 static int
-armpmu_map_event(u64 config)
+armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-       int mapping = (*armpmu->event_map)[config];
-       return mapping == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : mapping;
+       int mapping = (*event_map)[config];
+       return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
 static int
-armpmu_map_raw_event(u64 config)
+armpmu_map_raw_event(u32 raw_event_mask, u64 config)
 {
-       return (int)(config & armpmu->raw_event_mask);
+       return (int)(config & raw_event_mask);
 }
 
-static int
+static int map_cpu_event(struct perf_event *event,
+                        const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+                        const unsigned (*cache_map)
+                                       [PERF_COUNT_HW_CACHE_MAX]
+                                       [PERF_COUNT_HW_CACHE_OP_MAX]
+                                       [PERF_COUNT_HW_CACHE_RESULT_MAX],
+                        u32 raw_event_mask)
+{
+       u64 config = event->attr.config;
+
+       switch (event->attr.type) {
+       case PERF_TYPE_HARDWARE:
+               return armpmu_map_event(event_map, config);
+       case PERF_TYPE_HW_CACHE:
+               return armpmu_map_cache_event(cache_map, config);
+       case PERF_TYPE_RAW:
+               return armpmu_map_raw_event(raw_event_mask, config);
+       }
+
+       return -ENOENT;
+}
+
+int
 armpmu_event_set_period(struct perf_event *event,
                        struct hw_perf_event *hwc,
                        int idx)
 {
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        s64 left = local64_read(&hwc->period_left);
        s64 period = hwc->sample_period;
        int ret = 0;
@@ -202,11 +184,12 @@ armpmu_event_set_period(struct perf_event *event,
        return ret;
 }
 
-static u64
+u64
 armpmu_event_update(struct perf_event *event,
                    struct hw_perf_event *hwc,
                    int idx, int overflow)
 {
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        u64 delta, prev_raw_count, new_raw_count;
 
 again:
@@ -246,11 +229,9 @@ armpmu_read(struct perf_event *event)
 static void
 armpmu_stop(struct perf_event *event, int flags)
 {
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
 
-       if (!armpmu)
-               return;
-
        /*
         * ARM pmu always has to update the counter, so ignore
         * PERF_EF_UPDATE, see comments in armpmu_start().
@@ -266,11 +247,9 @@ armpmu_stop(struct perf_event *event, int flags)
 static void
 armpmu_start(struct perf_event *event, int flags)
 {
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
 
-       if (!armpmu)
-               return;
-
        /*
         * ARM pmu always has to reprogram the period, so ignore
         * PERF_EF_RELOAD, see the comment below.
@@ -293,16 +272,16 @@ armpmu_start(struct perf_event *event, int flags)
 static void
 armpmu_del(struct perf_event *event, int flags)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+       struct pmu_hw_events *hw_events = armpmu->get_hw_events();
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
 
        WARN_ON(idx < 0);
 
-       clear_bit(idx, cpuc->active_mask);
        armpmu_stop(event, PERF_EF_UPDATE);
-       cpuc->events[idx] = NULL;
-       clear_bit(idx, cpuc->used_mask);
+       hw_events->events[idx] = NULL;
+       clear_bit(idx, hw_events->used_mask);
 
        perf_event_update_userpage(event);
 }
@@ -310,7 +289,8 @@ armpmu_del(struct perf_event *event, int flags)
 static int
 armpmu_add(struct perf_event *event, int flags)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+       struct pmu_hw_events *hw_events = armpmu->get_hw_events();
        struct hw_perf_event *hwc = &event->hw;
        int idx;
        int err = 0;
@@ -318,7 +298,7 @@ armpmu_add(struct perf_event *event, int flags)
        perf_pmu_disable(event->pmu);
 
        /* If we don't have a space for the counter then finish early. */
-       idx = armpmu->get_event_idx(cpuc, hwc);
+       idx = armpmu->get_event_idx(hw_events, hwc);
        if (idx < 0) {
                err = idx;
                goto out;
@@ -330,8 +310,7 @@ armpmu_add(struct perf_event *event, int flags)
         */
        event->hw.idx = idx;
        armpmu->disable(hwc, idx);
-       cpuc->events[idx] = event;
-       set_bit(idx, cpuc->active_mask);
+       hw_events->events[idx] = event;
 
        hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
        if (flags & PERF_EF_START)
@@ -345,25 +324,25 @@ out:
        return err;
 }
 
-static struct pmu pmu;
-
 static int
-validate_event(struct cpu_hw_events *cpuc,
+validate_event(struct pmu_hw_events *hw_events,
               struct perf_event *event)
 {
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        struct hw_perf_event fake_event = event->hw;
+       struct pmu *leader_pmu = event->group_leader->pmu;
 
-       if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
+       if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
                return 1;
 
-       return armpmu->get_event_idx(cpuc, &fake_event) >= 0;
+       return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
 }
 
 static int
 validate_group(struct perf_event *event)
 {
        struct perf_event *sibling, *leader = event->group_leader;
-       struct cpu_hw_events fake_pmu;
+       struct pmu_hw_events fake_pmu;
 
        memset(&fake_pmu, 0, sizeof(fake_pmu));
 
@@ -383,110 +362,119 @@ validate_group(struct perf_event *event)
 
 static irqreturn_t armpmu_platform_irq(int irq, void *dev)
 {
-       struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev);
+       struct arm_pmu *armpmu = (struct arm_pmu *) dev;
+       struct platform_device *plat_device = armpmu->plat_device;
+       struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
 
        return plat->handle_irq(irq, dev, armpmu->handle_irq);
 }
 
+static void
+armpmu_release_hardware(struct arm_pmu *armpmu)
+{
+       int i, irq, irqs;
+       struct platform_device *pmu_device = armpmu->plat_device;
+
+       irqs = min(pmu_device->num_resources, num_possible_cpus());
+
+       for (i = 0; i < irqs; ++i) {
+               if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
+                       continue;
+               irq = platform_get_irq(pmu_device, i);
+               if (irq >= 0)
+                       free_irq(irq, armpmu);
+       }
+
+       release_pmu(armpmu->type);
+}
+
 static int
-armpmu_reserve_hardware(void)
+armpmu_reserve_hardware(struct arm_pmu *armpmu)
 {
        struct arm_pmu_platdata *plat;
        irq_handler_t handle_irq;
-       int i, err = -ENODEV, irq;
+       int i, err, irq, irqs;
+       struct platform_device *pmu_device = armpmu->plat_device;
 
-       pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
-       if (IS_ERR(pmu_device)) {
+       err = reserve_pmu(armpmu->type);
+       if (err) {
                pr_warning("unable to reserve pmu\n");
-               return PTR_ERR(pmu_device);
+               return err;
        }
 
-       init_pmu(ARM_PMU_DEVICE_CPU);
-
        plat = dev_get_platdata(&pmu_device->dev);
        if (plat && plat->handle_irq)
                handle_irq = armpmu_platform_irq;
        else
                handle_irq = armpmu->handle_irq;
 
-       if (pmu_device->num_resources < 1) {
+       irqs = min(pmu_device->num_resources, num_possible_cpus());
+       if (irqs < 1) {
                pr_err("no irqs for PMUs defined\n");
                return -ENODEV;
        }
 
-       for (i = 0; i < pmu_device->num_resources; ++i) {
+       for (i = 0; i < irqs; ++i) {
+               err = 0;
                irq = platform_get_irq(pmu_device, i);
                if (irq < 0)
                        continue;
 
+               /*
+                * If we have a single PMU interrupt that we can't shift,
+                * assume that we're running on a uniprocessor machine and
+                * continue. Otherwise, continue without this interrupt.
+                */
+               if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
+                       pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+                                   irq, i);
+                       continue;
+               }
+
                err = request_irq(irq, handle_irq,
                                  IRQF_DISABLED | IRQF_NOBALANCING,
-                                 "armpmu", NULL);
+                                 "arm-pmu", armpmu);
                if (err) {
-                       pr_warning("unable to request IRQ%d for ARM perf "
-                               "counters\n", irq);
-                       break;
+                       pr_err("unable to request IRQ%d for ARM PMU counters\n",
+                               irq);
+                       armpmu_release_hardware(armpmu);
+                       return err;
                }
-       }
 
-       if (err) {
-               for (i = i - 1; i >= 0; --i) {
-                       irq = platform_get_irq(pmu_device, i);
-                       if (irq >= 0)
-                               free_irq(irq, NULL);
-               }
-               release_pmu(ARM_PMU_DEVICE_CPU);
-               pmu_device = NULL;
+               cpumask_set_cpu(i, &armpmu->active_irqs);
        }
 
-       return err;
+       return 0;
 }
 
 static void
-armpmu_release_hardware(void)
+hw_perf_event_destroy(struct perf_event *event)
 {
-       int i, irq;
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+       atomic_t *active_events  = &armpmu->active_events;
+       struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex;
 
-       for (i = pmu_device->num_resources - 1; i >= 0; --i) {
-               irq = platform_get_irq(pmu_device, i);
-               if (irq >= 0)
-                       free_irq(irq, NULL);
+       if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) {
+               armpmu_release_hardware(armpmu);
+               mutex_unlock(pmu_reserve_mutex);
        }
-       armpmu->stop();
-
-       release_pmu(ARM_PMU_DEVICE_CPU);
-       pmu_device = NULL;
 }
 
-static atomic_t active_events = ATOMIC_INIT(0);
-static DEFINE_MUTEX(pmu_reserve_mutex);
-
-static void
-hw_perf_event_destroy(struct perf_event *event)
+static int
+event_requires_mode_exclusion(struct perf_event_attr *attr)
 {
-       if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) {
-               armpmu_release_hardware();
-               mutex_unlock(&pmu_reserve_mutex);
-       }
+       return attr->exclude_idle || attr->exclude_user ||
+              attr->exclude_kernel || attr->exclude_hv;
 }
 
 static int
 __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;
 
-       /* Decode the generic type into an ARM event identifier. */
-       if (PERF_TYPE_HARDWARE == event->attr.type) {
-               mapping = armpmu_map_event(event->attr.config);
-       } else if (PERF_TYPE_HW_CACHE == event->attr.type) {
-               mapping = armpmu_map_cache_event(event->attr.config);
-       } else if (PERF_TYPE_RAW == event->attr.type) {
-               mapping = armpmu_map_raw_event(event->attr.config);
-       } else {
-               pr_debug("event type %x not supported\n", event->attr.type);
-               return -EOPNOTSUPP;
-       }
+       mapping = armpmu->map_event(event);
 
        if (mapping < 0) {
                pr_debug("event %x:%llx not supported\n", event->attr.type,
@@ -494,35 +482,32 @@ __hw_perf_event_init(struct perf_event *event)
                return mapping;
        }
 
+       /*
+        * We don't assign an index until we actually place the event onto
+        * hardware. Use -1 to signify that we haven't decided where to put it
+        * yet. For SMP systems, each core has it's own PMU so we can't do any
+        * clever allocation or constraints checking at this point.
+        */
+       hwc->idx                = -1;
+       hwc->config_base        = 0;
+       hwc->config             = 0;
+       hwc->event_base         = 0;
+
        /*
         * Check whether we need to exclude the counter from certain modes.
-        * The ARM performance counters are on all of the time so if someone
-        * has asked us for some excludes then we have to fail.
         */
-       if (event->attr.exclude_kernel || event->attr.exclude_user ||
-           event->attr.exclude_hv || event->attr.exclude_idle) {
+       if ((!armpmu->set_event_filter ||
+            armpmu->set_event_filter(hwc, &event->attr)) &&
+            event_requires_mode_exclusion(&event->attr)) {
                pr_debug("ARM performance counters do not support "
                         "mode exclusion\n");
                return -EPERM;
        }
 
        /*
-        * We don't assign an index until we actually place the event onto
-        * hardware. Use -1 to signify that we haven't decided where to put it
-        * yet. For SMP systems, each core has it's own PMU so we can't do any
-        * clever allocation or constraints checking at this point.
+        * Store the event encoding into the config_base field.
         */
-       hwc->idx = -1;
-
-       /*
-        * Store the event encoding into the config_base field. config and
-        * event_base are unused as the only 2 things we need to know are
-        * the event mapping and the counter to use. The counter to use is
-        * also the indx and the config_base is the event type.
-        */
-       hwc->config_base            = (unsigned long)mapping;
-       hwc->config                 = 0;
-       hwc->event_base             = 0;
+       hwc->config_base            |= (unsigned long)mapping;
 
        if (!hwc->sample_period) {
                hwc->sample_period  = armpmu->max_period;
@@ -542,32 +527,23 @@ __hw_perf_event_init(struct perf_event *event)
 
 static int armpmu_event_init(struct perf_event *event)
 {
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        int err = 0;
+       atomic_t *active_events = &armpmu->active_events;
 
-       switch (event->attr.type) {
-       case PERF_TYPE_RAW:
-       case PERF_TYPE_HARDWARE:
-       case PERF_TYPE_HW_CACHE:
-               break;
-
-       default:
+       if (armpmu->map_event(event) == -ENOENT)
                return -ENOENT;
-       }
-
-       if (!armpmu)
-               return -ENODEV;
 
        event->destroy = hw_perf_event_destroy;
 
-       if (!atomic_inc_not_zero(&active_events)) {
-               mutex_lock(&pmu_reserve_mutex);
-               if (atomic_read(&active_events) == 0) {
-                       err = armpmu_reserve_hardware();
-               }
+       if (!atomic_inc_not_zero(active_events)) {
+               mutex_lock(&armpmu->reserve_mutex);
+               if (atomic_read(active_events) == 0)
+                       err = armpmu_reserve_hardware(armpmu);
 
                if (!err)
-                       atomic_inc(&active_events);
-               mutex_unlock(&pmu_reserve_mutex);
+                       atomic_inc(active_events);
+               mutex_unlock(&armpmu->reserve_mutex);
        }
 
        if (err)
@@ -582,22 +558,9 @@ static int armpmu_event_init(struct perf_event *event)
 
 static void armpmu_enable(struct pmu *pmu)
 {
-       /* Enable all of the perf events on hardware. */
-       int idx, enabled = 0;
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-
-       if (!armpmu)
-               return;
-
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
-               struct perf_event *event = cpuc->events[idx];
-
-               if (!event)
-                       continue;
-
-               armpmu->enable(&event->hw, idx);
-               enabled = 1;
-       }
+       struct arm_pmu *armpmu = to_arm_pmu(pmu);
+       struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+       int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
 
        if (enabled)
                armpmu->start();
@@ -605,20 +568,32 @@ static void armpmu_enable(struct pmu *pmu)
 
 static void armpmu_disable(struct pmu *pmu)
 {
-       if (armpmu)
-               armpmu->stop();
+       struct arm_pmu *armpmu = to_arm_pmu(pmu);
+       armpmu->stop();
 }
 
-static struct pmu pmu = {
-       .pmu_enable     = armpmu_enable,
-       .pmu_disable    = armpmu_disable,
-       .event_init     = armpmu_event_init,
-       .add            = armpmu_add,
-       .del            = armpmu_del,
-       .start          = armpmu_start,
-       .stop           = armpmu_stop,
-       .read           = armpmu_read,
-};
+static void __init armpmu_init(struct arm_pmu *armpmu)
+{
+       atomic_set(&armpmu->active_events, 0);
+       mutex_init(&armpmu->reserve_mutex);
+
+       armpmu->pmu = (struct pmu) {
+               .pmu_enable     = armpmu_enable,
+               .pmu_disable    = armpmu_disable,
+               .event_init     = armpmu_event_init,
+               .add            = armpmu_add,
+               .del            = armpmu_del,
+               .start          = armpmu_start,
+               .stop           = armpmu_stop,
+               .read           = armpmu_read,
+       };
+}
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+{
+       armpmu_init(armpmu);
+       return perf_pmu_register(&armpmu->pmu, name, type);
+}
 
 /* Include the PMU-specific implementations. */
 #include "perf_event_xscale.c"
@@ -630,14 +605,72 @@ static struct pmu pmu = {
  * This requires SMP to be available, so exists as a separate initcall.
  */
 static int __init
-armpmu_reset(void)
+cpu_pmu_reset(void)
+{
+       if (cpu_pmu && cpu_pmu->reset)
+               return on_each_cpu(cpu_pmu->reset, NULL, 1);
+       return 0;
+}
+arch_initcall(cpu_pmu_reset);
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id armpmu_of_device_ids[] = {
+       {.compatible = "arm,cortex-a9-pmu"},
+       {.compatible = "arm,cortex-a8-pmu"},
+       {.compatible = "arm,arm1136-pmu"},
+       {.compatible = "arm,arm1176-pmu"},
+       {},
+};
+
+static struct platform_device_id armpmu_plat_device_ids[] = {
+       {.name = "arm-pmu"},
+       {},
+};
+
+static int __devinit armpmu_device_probe(struct platform_device *pdev)
 {
-       if (armpmu && armpmu->reset)
-               return on_each_cpu(armpmu->reset, NULL, 1);
+       cpu_pmu->plat_device = pdev;
        return 0;
 }
-arch_initcall(armpmu_reset);
 
+static struct platform_driver armpmu_driver = {
+       .driver         = {
+               .name   = "arm-pmu",
+               .of_match_table = armpmu_of_device_ids,
+       },
+       .probe          = armpmu_device_probe,
+       .id_table       = armpmu_plat_device_ids,
+};
+
+static int __init register_pmu_driver(void)
+{
+       return platform_driver_register(&armpmu_driver);
+}
+device_initcall(register_pmu_driver);
+
+static struct pmu_hw_events *armpmu_get_cpu_events(void)
+{
+       return &__get_cpu_var(cpu_hw_events);
+}
+
+static void __init cpu_pmu_init(struct arm_pmu *armpmu)
+{
+       int cpu;
+       for_each_possible_cpu(cpu) {
+               struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
+               events->events = per_cpu(hw_events, cpu);
+               events->used_mask = per_cpu(used_mask, cpu);
+               raw_spin_lock_init(&events->pmu_lock);
+       }
+       armpmu->get_hw_events = armpmu_get_cpu_events;
+       armpmu->type = ARM_PMU_DEVICE_CPU;
+}
+
+/*
+ * CPU PMU identification and registration.
+ */
 static int __init
 init_hw_perf_events(void)
 {
@@ -651,22 +684,22 @@ init_hw_perf_events(void)
                case 0xB360:    /* ARM1136 */
                case 0xB560:    /* ARM1156 */
                case 0xB760:    /* ARM1176 */
-                       armpmu = armv6pmu_init();
+                       cpu_pmu = armv6pmu_init();
                        break;
                case 0xB020:    /* ARM11mpcore */
-                       armpmu = armv6mpcore_pmu_init();
+                       cpu_pmu = armv6mpcore_pmu_init();
                        break;
                case 0xC080:    /* Cortex-A8 */
-                       armpmu = armv7_a8_pmu_init();
+                       cpu_pmu = armv7_a8_pmu_init();
                        break;
                case 0xC090:    /* Cortex-A9 */
-                       armpmu = armv7_a9_pmu_init();
+                       cpu_pmu = armv7_a9_pmu_init();
                        break;
                case 0xC050:    /* Cortex-A5 */
-                       armpmu = armv7_a5_pmu_init();
+                       cpu_pmu = armv7_a5_pmu_init();
                        break;
                case 0xC0F0:    /* Cortex-A15 */
-                       armpmu = armv7_a15_pmu_init();
+                       cpu_pmu = armv7_a15_pmu_init();
                        break;
                }
        /* Intel CPUs [xscale]. */
@@ -674,23 +707,23 @@ init_hw_perf_events(void)
                part_number = (cpuid >> 13) & 0x7;
                switch (part_number) {
                case 1:
-                       armpmu = xscale1pmu_init();
+                       cpu_pmu = xscale1pmu_init();
                        break;
                case 2:
-                       armpmu = xscale2pmu_init();
+                       cpu_pmu = xscale2pmu_init();
                        break;
                }
        }
 
-       if (armpmu) {
+       if (cpu_pmu) {
                pr_info("enabled with %s PMU driver, %d counters available\n",
-                       armpmu->name, armpmu->num_events);
+                       cpu_pmu->name, cpu_pmu->num_events);
+               cpu_pmu_init(cpu_pmu);
+               armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
        } else {
                pr_info("no hardware support available\n");
        }
 
-       perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
-
        return 0;
 }
 early_initcall(init_hw_perf_events);
index dd7f3b9..e63d811 100644 (file)
@@ -54,7 +54,7 @@ enum armv6_perf_types {
 };
 
 enum armv6_counters {
-       ARMV6_CYCLE_COUNTER = 1,
+       ARMV6_CYCLE_COUNTER = 0,
        ARMV6_COUNTER0,
        ARMV6_COUNTER1,
 };
@@ -433,6 +433,7 @@ armv6pmu_enable_event(struct hw_perf_event *hwc,
                      int idx)
 {
        unsigned long val, mask, evt, flags;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        if (ARMV6_CYCLE_COUNTER == idx) {
                mask    = 0;
@@ -454,12 +455,29 @@ armv6pmu_enable_event(struct hw_perf_event *hwc,
         * Mask out the current event and set the counter to count the event
         * that we're interested in.
         */
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = armv6_pmcr_read();
        val &= ~mask;
        val |= evt;
        armv6_pmcr_write(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static int counter_is_active(unsigned long pmcr, int idx)
+{
+       unsigned long mask = 0;
+       if (idx == ARMV6_CYCLE_COUNTER)
+               mask = ARMV6_PMCR_CCOUNT_IEN;
+       else if (idx == ARMV6_COUNTER0)
+               mask = ARMV6_PMCR_COUNT0_IEN;
+       else if (idx == ARMV6_COUNTER1)
+               mask = ARMV6_PMCR_COUNT1_IEN;
+
+       if (mask)
+               return pmcr & mask;
+
+       WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+       return 0;
 }
 
 static irqreturn_t
@@ -468,7 +486,7 @@ armv6pmu_handle_irq(int irq_num,
 {
        unsigned long pmcr = armv6_pmcr_read();
        struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
+       struct pmu_hw_events *cpuc;
        struct pt_regs *regs;
        int idx;
 
@@ -487,11 +505,11 @@ armv6pmu_handle_irq(int irq_num,
        perf_sample_data_init(&data, 0);
 
        cpuc = &__get_cpu_var(cpu_hw_events);
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+       for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
 
-               if (!test_bit(idx, cpuc->active_mask))
+               if (!counter_is_active(pmcr, idx))
                        continue;
 
                /*
@@ -508,7 +526,7 @@ armv6pmu_handle_irq(int irq_num,
                        continue;
 
                if (perf_event_overflow(event, &data, regs))
-                       armpmu->disable(hwc, idx);
+                       cpu_pmu->disable(hwc, idx);
        }
 
        /*
@@ -527,28 +545,30 @@ static void
 armv6pmu_start(void)
 {
        unsigned long flags, val;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = armv6_pmcr_read();
        val |= ARMV6_PMCR_ENABLE;
        armv6_pmcr_write(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 armv6pmu_stop(void)
 {
        unsigned long flags, val;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = armv6_pmcr_read();
        val &= ~ARMV6_PMCR_ENABLE;
        armv6_pmcr_write(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
+armv6pmu_get_event_idx(struct pmu_hw_events *cpuc,
                       struct hw_perf_event *event)
 {
        /* Always place a cycle counter into the cycle counter. */
@@ -578,6 +598,7 @@ armv6pmu_disable_event(struct hw_perf_event *hwc,
                       int idx)
 {
        unsigned long val, mask, evt, flags;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        if (ARMV6_CYCLE_COUNTER == idx) {
                mask    = ARMV6_PMCR_CCOUNT_IEN;
@@ -598,12 +619,12 @@ armv6pmu_disable_event(struct hw_perf_event *hwc,
         * of ETM bus signal assertion cycles. The external reporting should
         * be disabled and so this should never increment.
         */
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = armv6_pmcr_read();
        val &= ~mask;
        val |= evt;
        armv6_pmcr_write(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
@@ -611,6 +632,7 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
                              int idx)
 {
        unsigned long val, mask, flags, evt = 0;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        if (ARMV6_CYCLE_COUNTER == idx) {
                mask    = ARMV6_PMCR_CCOUNT_IEN;
@@ -627,15 +649,21 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
         * Unlike UP ARMv6, we don't have a way of stopping the counters. We
         * simply disable the interrupt reporting.
         */
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = armv6_pmcr_read();
        val &= ~mask;
        val |= evt;
        armv6_pmcr_write(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static int armv6_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &armv6_perf_map,
+                               &armv6_perf_cache_map, 0xFF);
 }
 
-static const struct arm_pmu armv6pmu = {
+static struct arm_pmu armv6pmu = {
        .id                     = ARM_PERF_PMU_ID_V6,
        .name                   = "v6",
        .handle_irq             = armv6pmu_handle_irq,
@@ -646,14 +674,12 @@ static const struct arm_pmu armv6pmu = {
        .get_event_idx          = armv6pmu_get_event_idx,
        .start                  = armv6pmu_start,
        .stop                   = armv6pmu_stop,
-       .cache_map              = &armv6_perf_cache_map,
-       .event_map              = &armv6_perf_map,
-       .raw_event_mask         = 0xFF,
+       .map_event              = armv6_map_event,
        .num_events             = 3,
        .max_period             = (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__init armv6pmu_init(void)
 {
        return &armv6pmu;
 }
@@ -665,7 +691,14 @@ static const struct arm_pmu *__init armv6pmu_init(void)
  * disable the interrupt reporting and update the event. When unthrottling we
  * reset the period and enable the interrupt reporting.
  */
-static const struct arm_pmu armv6mpcore_pmu = {
+
+static int armv6mpcore_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &armv6mpcore_perf_map,
+                               &armv6mpcore_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu armv6mpcore_pmu = {
        .id                     = ARM_PERF_PMU_ID_V6MP,
        .name                   = "v6mpcore",
        .handle_irq             = armv6pmu_handle_irq,
@@ -676,24 +709,22 @@ static const struct arm_pmu armv6mpcore_pmu = {
        .get_event_idx          = armv6pmu_get_event_idx,
        .start                  = armv6pmu_start,
        .stop                   = armv6pmu_stop,
-       .cache_map              = &armv6mpcore_perf_cache_map,
-       .event_map              = &armv6mpcore_perf_map,
-       .raw_event_mask         = 0xFF,
+       .map_event              = armv6mpcore_map_event,
        .num_events             = 3,
        .max_period             = (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__init armv6mpcore_pmu_init(void)
 {
        return &armv6mpcore_pmu;
 }
 #else
-static const struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__init armv6pmu_init(void)
 {
        return NULL;
 }
 
-static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__init armv6mpcore_pmu_init(void)
 {
        return NULL;
 }
index 4c85183..98b7573 100644 (file)
@@ -17,6 +17,9 @@
  */
 
 #ifdef CONFIG_CPU_V7
+
+static struct arm_pmu armv7pmu;
+
 /*
  * Common ARMv7 event types
  *
@@ -676,23 +679,24 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 };
 
 /*
- * Perf Events counters
+ * Perf Events' indices
  */
-enum armv7_counters {
-       ARMV7_CYCLE_COUNTER             = 1,    /* Cycle counter */
-       ARMV7_COUNTER0                  = 2,    /* First event counter */
-};
+#define        ARMV7_IDX_CYCLE_COUNTER 0
+#define        ARMV7_IDX_COUNTER0      1
+#define        ARMV7_IDX_COUNTER_LAST  (ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
+
+#define        ARMV7_MAX_COUNTERS      32
+#define        ARMV7_COUNTER_MASK      (ARMV7_MAX_COUNTERS - 1)
 
 /*
- * The cycle counter is ARMV7_CYCLE_COUNTER.
- * The first event counter is ARMV7_COUNTER0.
- * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
+ * ARMv7 low level PMNC access
  */
-#define        ARMV7_COUNTER_LAST      (ARMV7_COUNTER0 + armpmu->num_events - 1)
 
 /*
- * ARMv7 low level PMNC access
+ * Perf Event to low level counters mapping
  */
+#define        ARMV7_IDX_TO_COUNTER(x) \
+       (((x) - ARMV7_IDX_COUNTER0) & ARMV7_COUNTER_MASK)
 
 /*
  * Per-CPU PMNC: config reg
@@ -708,103 +712,76 @@ enum armv7_counters {
 #define        ARMV7_PMNC_MASK         0x3f     /* Mask for writable bits */
 
 /*
- * Available counters
- */
-#define ARMV7_CNT0             0       /* First event counter */
-#define ARMV7_CCNT             31      /* Cycle counter */
-
-/* Perf Event to low level counters mapping */
-#define ARMV7_EVENT_CNT_TO_CNTx        (ARMV7_COUNTER0 - ARMV7_CNT0)
-
-/*
- * CNTENS: counters enable reg
- */
-#define ARMV7_CNTENS_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENS_C         (1 << ARMV7_CCNT)
-
-/*
- * CNTENC: counters disable reg
- */
-#define ARMV7_CNTENC_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENC_C         (1 << ARMV7_CCNT)
-
-/*
- * INTENS: counters overflow interrupt enable reg
- */
-#define ARMV7_INTENS_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENS_C         (1 << ARMV7_CCNT)
-
-/*
- * INTENC: counters overflow interrupt disable reg
- */
-#define ARMV7_INTENC_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENC_C         (1 << ARMV7_CCNT)
-
-/*
- * EVTSEL: Event selection reg
+ * FLAG: counters overflow flag status reg
  */
-#define        ARMV7_EVTSEL_MASK       0xff            /* Mask for writable bits */
+#define        ARMV7_FLAG_MASK         0xffffffff      /* Mask for writable bits */
+#define        ARMV7_OVERFLOWED_MASK   ARMV7_FLAG_MASK
 
 /*
- * SELECT: Counter selection reg
+ * PMXEVTYPER: Event selection reg
  */
-#define        ARMV7_SELECT_MASK       0x1f            /* Mask for writable bits */
+#define        ARMV7_EVTYPE_MASK       0xc00000ff      /* Mask for writable bits */
+#define        ARMV7_EVTYPE_EVENT      0xff            /* Mask for EVENT bits */
 
 /*
- * FLAG: counters overflow flag status reg
+ * Event filters for PMUv2
  */
-#define ARMV7_FLAG_P(idx)      (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_FLAG_C           (1 << ARMV7_CCNT)
-#define        ARMV7_FLAG_MASK         0xffffffff      /* Mask for writable bits */
-#define        ARMV7_OVERFLOWED_MASK   ARMV7_FLAG_MASK
+#define        ARMV7_EXCLUDE_PL1       (1 << 31)
+#define        ARMV7_EXCLUDE_USER      (1 << 30)
+#define        ARMV7_INCLUDE_HYP       (1 << 27)
 
-static inline unsigned long armv7_pmnc_read(void)
+static inline u32 armv7_pmnc_read(void)
 {
        u32 val;
        asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
        return val;
 }
 
-static inline void armv7_pmnc_write(unsigned long val)
+static inline void armv7_pmnc_write(u32 val)
 {
        val &= ARMV7_PMNC_MASK;
        isb();
        asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
 }
 
-static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
+static inline int armv7_pmnc_has_overflowed(u32 pmnc)
 {
        return pmnc & ARMV7_OVERFLOWED_MASK;
 }
 
-static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
-                                       enum armv7_counters counter)
+static inline int armv7_pmnc_counter_valid(int idx)
+{
+       return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST;
+}
+
+static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx)
 {
        int ret = 0;
+       u32 counter;
 
-       if (counter == ARMV7_CYCLE_COUNTER)
-               ret = pmnc & ARMV7_FLAG_C;
-       else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
-               ret = pmnc & ARMV7_FLAG_P(counter);
-       else
+       if (!armv7_pmnc_counter_valid(idx)) {
                pr_err("CPU%u checking wrong counter %d overflow status\n",
-                       smp_processor_id(), counter);
+                       smp_processor_id(), idx);
+       } else {
+               counter = ARMV7_IDX_TO_COUNTER(idx);
+               ret = pmnc & BIT(counter);
+       }
 
        return ret;
 }
 
-static inline int armv7_pmnc_select_counter(unsigned int idx)
+static inline int armv7_pmnc_select_counter(int idx)
 {
-       u32 val;
+       u32 counter;
 
-       if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
-               pr_err("CPU%u selecting wrong PMNC counter"
-                       " %d\n", smp_processor_id(), idx);
-               return -1;
+       if (!armv7_pmnc_counter_valid(idx)) {
+               pr_err("CPU%u selecting wrong PMNC counter %d\n",
+                       smp_processor_id(), idx);
+               return -EINVAL;
        }
 
-       val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
-       asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+       counter = ARMV7_IDX_TO_COUNTER(idx);
+       asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter));
        isb();
 
        return idx;
@@ -812,124 +789,95 @@ static inline int armv7_pmnc_select_counter(unsigned int idx)
 
 static inline u32 armv7pmu_read_counter(int idx)
 {
-       unsigned long value = 0;
+       u32 value = 0;
 
-       if (idx == ARMV7_CYCLE_COUNTER)
-               asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
-       else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
-               if (armv7_pmnc_select_counter(idx) == idx)
-                       asm volatile("mrc p15, 0, %0, c9, c13, 2"
-                                    : "=r" (value));
-       } else
+       if (!armv7_pmnc_counter_valid(idx))
                pr_err("CPU%u reading wrong counter %d\n",
                        smp_processor_id(), idx);
+       else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+               asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
+       else if (armv7_pmnc_select_counter(idx) == idx)
+               asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (value));
 
        return value;
 }
 
 static inline void armv7pmu_write_counter(int idx, u32 value)
 {
-       if (idx == ARMV7_CYCLE_COUNTER)
-               asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
-       else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
-               if (armv7_pmnc_select_counter(idx) == idx)
-                       asm volatile("mcr p15, 0, %0, c9, c13, 2"
-                                    : : "r" (value));
-       } else
+       if (!armv7_pmnc_counter_valid(idx))
                pr_err("CPU%u writing wrong counter %d\n",
                        smp_processor_id(), idx);
+       else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+               asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
+       else if (armv7_pmnc_select_counter(idx) == idx)
+               asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value));
 }
 
-static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
+static inline void armv7_pmnc_write_evtsel(int idx, u32 val)
 {
        if (armv7_pmnc_select_counter(idx) == idx) {
-               val &= ARMV7_EVTSEL_MASK;
+               val &= ARMV7_EVTYPE_MASK;
                asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
        }
 }
 
-static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
+static inline int armv7_pmnc_enable_counter(int idx)
 {
-       u32 val;
+       u32 counter;
 
-       if ((idx != ARMV7_CYCLE_COUNTER) &&
-           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-               pr_err("CPU%u enabling wrong PMNC counter"
-                       " %d\n", smp_processor_id(), idx);
-               return -1;
+       if (!armv7_pmnc_counter_valid(idx)) {
+               pr_err("CPU%u enabling wrong PMNC counter %d\n",
+                       smp_processor_id(), idx);
+               return -EINVAL;
        }
 
-       if (idx == ARMV7_CYCLE_COUNTER)
-               val = ARMV7_CNTENS_C;
-       else
-               val = ARMV7_CNTENS_P(idx);
-
-       asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
-
+       counter = ARMV7_IDX_TO_COUNTER(idx);
+       asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter)));
        return idx;
 }
 
-static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
+static inline int armv7_pmnc_disable_counter(int idx)
 {
-       u32 val;
-
+       u32 counter;
 
-       if ((idx != ARMV7_CYCLE_COUNTER) &&
-           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-               pr_err("CPU%u disabling wrong PMNC counter"
-                       " %d\n", smp_processor_id(), idx);
-               return -1;
+       if (!armv7_pmnc_counter_valid(idx)) {
+               pr_err("CPU%u disabling wrong PMNC counter %d\n",
+                       smp_processor_id(), idx);
+               return -EINVAL;
        }
 
-       if (idx == ARMV7_CYCLE_COUNTER)
-               val = ARMV7_CNTENC_C;
-       else
-               val = ARMV7_CNTENC_P(idx);
-
-       asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
-
+       counter = ARMV7_IDX_TO_COUNTER(idx);
+       asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter)));
        return idx;
 }
 
-static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
+static inline int armv7_pmnc_enable_intens(int idx)
 {
-       u32 val;
+       u32 counter;
 
-       if ((idx != ARMV7_CYCLE_COUNTER) &&
-           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-               pr_err("CPU%u enabling wrong PMNC counter"
-                       " interrupt enable %d\n", smp_processor_id(), idx);
-               return -1;
+       if (!armv7_pmnc_counter_valid(idx)) {
+               pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
+                       smp_processor_id(), idx);
+               return -EINVAL;
        }
 
-       if (idx == ARMV7_CYCLE_COUNTER)
-               val = ARMV7_INTENS_C;
-       else
-               val = ARMV7_INTENS_P(idx);
-
-       asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
-
+       counter = ARMV7_IDX_TO_COUNTER(idx);
+       asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter)));
        return idx;
 }
 
-static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
+static inline int armv7_pmnc_disable_intens(int idx)
 {
-       u32 val;
+       u32 counter;
 
-       if ((idx != ARMV7_CYCLE_COUNTER) &&
-           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-               pr_err("CPU%u disabling wrong PMNC counter"
-                       " interrupt enable %d\n", smp_processor_id(), idx);
-               return -1;
+       if (!armv7_pmnc_counter_valid(idx)) {
+               pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
+                       smp_processor_id(), idx);
+               return -EINVAL;
        }
 
-       if (idx == ARMV7_CYCLE_COUNTER)
-               val = ARMV7_INTENC_C;
-       else
-               val = ARMV7_INTENC_P(idx);
-
-       asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
-
+       counter = ARMV7_IDX_TO_COUNTER(idx);
+       asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter)));
        return idx;
 }
 
@@ -973,14 +921,14 @@ static void armv7_pmnc_dump_regs(void)
        asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
        printk(KERN_INFO "CCNT  =0x%08x\n", val);
 
-       for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
+       for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) {
                armv7_pmnc_select_counter(cnt);
                asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
                printk(KERN_INFO "CNT[%d] count =0x%08x\n",
-                       cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+                       ARMV7_IDX_TO_COUNTER(cnt), val);
                asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
                printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
-                       cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+                       ARMV7_IDX_TO_COUNTER(cnt), val);
        }
 }
 #endif
@@ -988,12 +936,13 @@ static void armv7_pmnc_dump_regs(void)
 static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
        unsigned long flags;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        /*
         * Enable counter and interrupt, and set the counter to count
         * the event that we're interested in.
         */
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
 
        /*
         * Disable counter
@@ -1002,9 +951,10 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
 
        /*
         * Set event (if destined for PMNx counters)
-        * We don't need to set the event if it's a cycle count
+        * We only need to set the event for the cycle counter if we
+        * have the ability to perform event filtering.
         */
-       if (idx != ARMV7_CYCLE_COUNTER)
+       if (armv7pmu.set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER)
                armv7_pmnc_write_evtsel(idx, hwc->config_base);
 
        /*
@@ -1017,17 +967,18 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
         */
        armv7_pmnc_enable_counter(idx);
 
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
        unsigned long flags;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        /*
         * Disable counter and interrupt
         */
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
 
        /*
         * Disable counter
@@ -1039,14 +990,14 @@ static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
         */
        armv7_pmnc_disable_intens(idx);
 
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 {
-       unsigned long pmnc;
+       u32 pmnc;
        struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
+       struct pmu_hw_events *cpuc;
        struct pt_regs *regs;
        int idx;
 
@@ -1069,13 +1020,10 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
        perf_sample_data_init(&data, 0);
 
        cpuc = &__get_cpu_var(cpu_hw_events);
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+       for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
 
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
                /*
                 * We have a single interrupt for all counters. Check that
                 * each counter has overflowed before we process it.
@@ -1090,7 +1038,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
                        continue;
 
                if (perf_event_overflow(event, &data, regs))
-                       armpmu->disable(hwc, idx);
+                       cpu_pmu->disable(hwc, idx);
        }
 
        /*
@@ -1108,61 +1056,114 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 static void armv7pmu_start(void)
 {
        unsigned long flags;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        /* Enable all counters */
        armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void armv7pmu_stop(void)
 {
        unsigned long flags;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        /* Disable all counters */
        armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
+static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc,
                                  struct hw_perf_event *event)
 {
        int idx;
+       unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT;
 
        /* Always place a cycle counter into the cycle counter. */
-       if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
-               if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
+       if (evtype == ARMV7_PERFCTR_CPU_CYCLES) {
+               if (test_and_set_bit(ARMV7_IDX_CYCLE_COUNTER, cpuc->used_mask))
                        return -EAGAIN;
 
-               return ARMV7_CYCLE_COUNTER;
-       } else {
-               /*
-                * For anything other than a cycle counter, try and use
-                * the events counters
-                */
-               for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
-                       if (!test_and_set_bit(idx, cpuc->used_mask))
-                               return idx;
-               }
+               return ARMV7_IDX_CYCLE_COUNTER;
+       }
 
-               /* The counters are all in use. */
-               return -EAGAIN;
+       /*
+        * For anything other than a cycle counter, try and use
+        * the events counters
+        */
+       for (idx = ARMV7_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) {
+               if (!test_and_set_bit(idx, cpuc->used_mask))
+                       return idx;
        }
+
+       /* The counters are all in use. */
+       return -EAGAIN;
+}
+
+/*
+ * Add an event filter to a given event. This will only work for PMUv2 PMUs.
+ */
+static int armv7pmu_set_event_filter(struct hw_perf_event *event,
+                                    struct perf_event_attr *attr)
+{
+       unsigned long config_base = 0;
+
+       if (attr->exclude_idle)
+               return -EPERM;
+       if (attr->exclude_user)
+               config_base |= ARMV7_EXCLUDE_USER;
+       if (attr->exclude_kernel)
+               config_base |= ARMV7_EXCLUDE_PL1;
+       if (!attr->exclude_hv)
+               config_base |= ARMV7_INCLUDE_HYP;
+
+       /*
+        * Install the filter into config_base as this is used to
+        * construct the event type.
+        */
+       event->config_base = config_base;
+
+       return 0;
 }
 
 static void armv7pmu_reset(void *info)
 {
-       u32 idx, nb_cnt = armpmu->num_events;
+       u32 idx, nb_cnt = cpu_pmu->num_events;
 
        /* The counter and interrupt enable registers are unknown at reset. */
-       for (idx = 1; idx < nb_cnt; ++idx)
+       for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx)
                armv7pmu_disable_event(NULL, idx);
 
        /* Initialize & Reset PMNC: C and P bits */
        armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
 }
 
+static int armv7_a8_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &armv7_a8_perf_map,
+                               &armv7_a8_perf_cache_map, 0xFF);
+}
+
+static int armv7_a9_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &armv7_a9_perf_map,
+                               &armv7_a9_perf_cache_map, 0xFF);
+}
+
+static int armv7_a5_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &armv7_a5_perf_map,
+                               &armv7_a5_perf_cache_map, 0xFF);
+}
+
+static int armv7_a15_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &armv7_a15_perf_map,
+                               &armv7_a15_perf_cache_map, 0xFF);
+}
+
 static struct arm_pmu armv7pmu = {
        .handle_irq             = armv7pmu_handle_irq,
        .enable                 = armv7pmu_enable_event,
@@ -1173,7 +1174,6 @@ static struct arm_pmu armv7pmu = {
        .start                  = armv7pmu_start,
        .stop                   = armv7pmu_stop,
        .reset                  = armv7pmu_reset,
-       .raw_event_mask         = 0xFF,
        .max_period             = (1LLU << 32) - 1,
 };
 
@@ -1188,62 +1188,59 @@ static u32 __init armv7_read_num_pmnc_events(void)
        return nb_cnt + 1;
 }
 
-static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
        armv7pmu.id             = ARM_PERF_PMU_ID_CA8;
        armv7pmu.name           = "ARMv7 Cortex-A8";
-       armv7pmu.cache_map      = &armv7_a8_perf_cache_map;
-       armv7pmu.event_map      = &armv7_a8_perf_map;
+       armv7pmu.map_event      = armv7_a8_map_event;
        armv7pmu.num_events     = armv7_read_num_pmnc_events();
        return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__init armv7_a9_pmu_init(void)
 {
        armv7pmu.id             = ARM_PERF_PMU_ID_CA9;
        armv7pmu.name           = "ARMv7 Cortex-A9";
-       armv7pmu.cache_map      = &armv7_a9_perf_cache_map;
-       armv7pmu.event_map      = &armv7_a9_perf_map;
+       armv7pmu.map_event      = armv7_a9_map_event;
        armv7pmu.num_events     = armv7_read_num_pmnc_events();
        return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__init armv7_a5_pmu_init(void)
 {
        armv7pmu.id             = ARM_PERF_PMU_ID_CA5;
        armv7pmu.name           = "ARMv7 Cortex-A5";
-       armv7pmu.cache_map      = &armv7_a5_perf_cache_map;
-       armv7pmu.event_map      = &armv7_a5_perf_map;
+       armv7pmu.map_event      = armv7_a5_map_event;
        armv7pmu.num_events     = armv7_read_num_pmnc_events();
        return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__init armv7_a15_pmu_init(void)
 {
        armv7pmu.id             = ARM_PERF_PMU_ID_CA15;
        armv7pmu.name           = "ARMv7 Cortex-A15";
-       armv7pmu.cache_map      = &armv7_a15_perf_cache_map;
-       armv7pmu.event_map      = &armv7_a15_perf_map;
+       armv7pmu.map_event      = armv7_a15_map_event;
        armv7pmu.num_events     = armv7_read_num_pmnc_events();
+       armv7pmu.set_event_filter = armv7pmu_set_event_filter;
        return &armv7pmu;
 }
 #else
-static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
        return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__init armv7_a9_pmu_init(void)
 {
        return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__init armv7_a5_pmu_init(void)
 {
        return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__init armv7_a15_pmu_init(void)
 {
        return NULL;
 }
index 3c43974..e0cca10 100644 (file)
@@ -40,7 +40,7 @@ enum xscale_perf_types {
 };
 
 enum xscale_counters {
-       XSCALE_CYCLE_COUNTER    = 1,
+       XSCALE_CYCLE_COUNTER    = 0,
        XSCALE_COUNTER0,
        XSCALE_COUNTER1,
        XSCALE_COUNTER2,
@@ -222,7 +222,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
 {
        unsigned long pmnc;
        struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
+       struct pmu_hw_events *cpuc;
        struct pt_regs *regs;
        int idx;
 
@@ -249,13 +249,10 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
        perf_sample_data_init(&data, 0);
 
        cpuc = &__get_cpu_var(cpu_hw_events);
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+       for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
 
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
                if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
                        continue;
 
@@ -266,7 +263,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
                        continue;
 
                if (perf_event_overflow(event, &data, regs))
-                       armpmu->disable(hwc, idx);
+                       cpu_pmu->disable(hwc, idx);
        }
 
        irq_work_run();
@@ -284,6 +281,7 @@ static void
 xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
        unsigned long val, mask, evt, flags;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        switch (idx) {
        case XSCALE_CYCLE_COUNTER:
@@ -305,18 +303,19 @@ xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
                return;
        }
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale1pmu_read_pmnc();
        val &= ~mask;
        val |= evt;
        xscale1pmu_write_pmnc(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
        unsigned long val, mask, evt, flags;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        switch (idx) {
        case XSCALE_CYCLE_COUNTER:
@@ -336,16 +335,16 @@ xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
                return;
        }
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale1pmu_read_pmnc();
        val &= ~mask;
        val |= evt;
        xscale1pmu_write_pmnc(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
+xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
                        struct hw_perf_event *event)
 {
        if (XSCALE_PERFCTR_CCNT == event->config_base) {
@@ -368,24 +367,26 @@ static void
 xscale1pmu_start(void)
 {
        unsigned long flags, val;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale1pmu_read_pmnc();
        val |= XSCALE_PMU_ENABLE;
        xscale1pmu_write_pmnc(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale1pmu_stop(void)
 {
        unsigned long flags, val;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale1pmu_read_pmnc();
        val &= ~XSCALE_PMU_ENABLE;
        xscale1pmu_write_pmnc(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static inline u32
@@ -424,7 +425,13 @@ xscale1pmu_write_counter(int counter, u32 val)
        }
 }
 
-static const struct arm_pmu xscale1pmu = {
+static int xscale_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &xscale_perf_map,
+                               &xscale_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu xscale1pmu = {
        .id             = ARM_PERF_PMU_ID_XSCALE1,
        .name           = "xscale1",
        .handle_irq     = xscale1pmu_handle_irq,
@@ -435,14 +442,12 @@ static const struct arm_pmu xscale1pmu = {
        .get_event_idx  = xscale1pmu_get_event_idx,
        .start          = xscale1pmu_start,
        .stop           = xscale1pmu_stop,
-       .cache_map      = &xscale_perf_cache_map,
-       .event_map      = &xscale_perf_map,
-       .raw_event_mask = 0xFF,
+       .map_event      = xscale_map_event,
        .num_events     = 3,
        .max_period     = (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__init xscale1pmu_init(void)
 {
        return &xscale1pmu;
 }
@@ -560,7 +565,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
 {
        unsigned long pmnc, of_flags;
        struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
+       struct pmu_hw_events *cpuc;
        struct pt_regs *regs;
        int idx;
 
@@ -581,13 +586,10 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
        perf_sample_data_init(&data, 0);
 
        cpuc = &__get_cpu_var(cpu_hw_events);
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+       for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
                struct perf_event *event = cpuc->events[idx];
                struct hw_perf_event *hwc;
 
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
                if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx))
                        continue;
 
@@ -598,7 +600,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
                        continue;
 
                if (perf_event_overflow(event, &data, regs))
-                       armpmu->disable(hwc, idx);
+                       cpu_pmu->disable(hwc, idx);
        }
 
        irq_work_run();
@@ -616,6 +618,7 @@ static void
 xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
        unsigned long flags, ien, evtsel;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        ien = xscale2pmu_read_int_enable();
        evtsel = xscale2pmu_read_event_select();
@@ -649,16 +652,17 @@ xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
                return;
        }
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        xscale2pmu_write_event_select(evtsel);
        xscale2pmu_write_int_enable(ien);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
        unsigned long flags, ien, evtsel;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
        ien = xscale2pmu_read_int_enable();
        evtsel = xscale2pmu_read_event_select();
@@ -692,14 +696,14 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
                return;
        }
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        xscale2pmu_write_event_select(evtsel);
        xscale2pmu_write_int_enable(ien);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
+xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
                        struct hw_perf_event *event)
 {
        int idx = xscale1pmu_get_event_idx(cpuc, event);
@@ -718,24 +722,26 @@ static void
 xscale2pmu_start(void)
 {
        unsigned long flags, val;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
        val |= XSCALE_PMU_ENABLE;
        xscale2pmu_write_pmnc(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale2pmu_stop(void)
 {
        unsigned long flags, val;
+       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-       raw_spin_lock_irqsave(&pmu_lock, flags);
+       raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale2pmu_read_pmnc();
        val &= ~XSCALE_PMU_ENABLE;
        xscale2pmu_write_pmnc(val);
-       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static inline u32
@@ -786,7 +792,7 @@ xscale2pmu_write_counter(int counter, u32 val)
        }
 }
 
-static const struct arm_pmu xscale2pmu = {
+static struct arm_pmu xscale2pmu = {
        .id             = ARM_PERF_PMU_ID_XSCALE2,
        .name           = "xscale2",
        .handle_irq     = xscale2pmu_handle_irq,
@@ -797,24 +803,22 @@ static const struct arm_pmu xscale2pmu = {
        .get_event_idx  = xscale2pmu_get_event_idx,
        .start          = xscale2pmu_start,
        .stop           = xscale2pmu_stop,
-       .cache_map      = &xscale_perf_cache_map,
-       .event_map      = &xscale_perf_map,
-       .raw_event_mask = 0xFF,
+       .map_event      = xscale_map_event,
        .num_events     = 5,
        .max_period     = (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__init xscale2pmu_init(void)
 {
        return &xscale2pmu;
 }
 #else
-static const struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__init xscale1pmu_init(void)
 {
        return NULL;
 }
 
-static const struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__init xscale2pmu_init(void)
 {
        return NULL;
 }
index c53474f..2c3407e 100644 (file)
  *
  */
 
-#define pr_fmt(fmt) "PMU: " fmt
-
-#include <linux/cpumask.h>
 #include <linux/err.h>
-#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
 
 #include <asm/pmu.h>
 
-static volatile long pmu_lock;
-
-static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES];
-
-static int __devinit pmu_register(struct platform_device *pdev,
-                                       enum arm_pmu_type type)
-{
-       if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {
-               pr_warning("received registration request for unknown "
-                               "PMU device type %d\n", type);
-               return -EINVAL;
-       }
-
-       if (pmu_devices[type]) {
-               pr_warning("rejecting duplicate registration of PMU device "
-                       "type %d.", type);
-               return -ENOSPC;
-       }
-
-       pr_info("registered new PMU device of type %d\n", type);
-       pmu_devices[type] = pdev;
-       return 0;
-}
-
-#define OF_MATCH_PMU(_name, _type) {   \
-       .compatible = _name,            \
-       .data = (void *)_type,          \
-}
-
-#define OF_MATCH_CPU(name)     OF_MATCH_PMU(name, ARM_PMU_DEVICE_CPU)
-
-static struct of_device_id armpmu_of_device_ids[] = {
-       OF_MATCH_CPU("arm,cortex-a9-pmu"),
-       OF_MATCH_CPU("arm,cortex-a8-pmu"),
-       OF_MATCH_CPU("arm,arm1136-pmu"),
-       OF_MATCH_CPU("arm,arm1176-pmu"),
-       {},
-};
-
-#define PLAT_MATCH_PMU(_name, _type) { \
-       .name           = _name,        \
-       .driver_data    = _type,        \
-}
-
-#define PLAT_MATCH_CPU(_name)  PLAT_MATCH_PMU(_name, ARM_PMU_DEVICE_CPU)
-
-static struct platform_device_id armpmu_plat_device_ids[] = {
-       PLAT_MATCH_CPU("arm-pmu"),
-       {},
-};
-
-enum arm_pmu_type armpmu_device_type(struct platform_device *pdev)
-{
-       const struct of_device_id       *of_id;
-       const struct platform_device_id *pdev_id;
-
-       /* provided by of_device_id table */
-       if (pdev->dev.of_node) {
-               of_id = of_match_device(armpmu_of_device_ids, &pdev->dev);
-               BUG_ON(!of_id);
-               return (enum arm_pmu_type)of_id->data;
-       }
-
-       /* Provided by platform_device_id table */
-       pdev_id = platform_get_device_id(pdev);
-       BUG_ON(!pdev_id);
-       return pdev_id->driver_data;
-}
-
-static int __devinit armpmu_device_probe(struct platform_device *pdev)
-{
-       return pmu_register(pdev, armpmu_device_type(pdev));
-}
-
-static struct platform_driver armpmu_driver = {
-       .driver         = {
-               .name   = "arm-pmu",
-               .of_match_table = armpmu_of_device_ids,
-       },
-       .probe          = armpmu_device_probe,
-       .id_table       = armpmu_plat_device_ids,
-};
-
-static int __init register_pmu_driver(void)
-{
-       return platform_driver_register(&armpmu_driver);
-}
-device_initcall(register_pmu_driver);
+/*
+ * PMU locking to ensure mutual exclusion between different subsystems.
+ */
+static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)];
 
-struct platform_device *
+int
 reserve_pmu(enum arm_pmu_type type)
 {
-       struct platform_device *pdev;
-
-       if (test_and_set_bit_lock(type, &pmu_lock)) {
-               pdev = ERR_PTR(-EBUSY);
-       } else if (pmu_devices[type] == NULL) {
-               clear_bit_unlock(type, &pmu_lock);
-               pdev = ERR_PTR(-ENODEV);
-       } else {
-               pdev = pmu_devices[type];
-       }
-
-       return pdev;
+       return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0;
 }
 EXPORT_SYMBOL_GPL(reserve_pmu);
 
-int
+void
 release_pmu(enum arm_pmu_type type)
 {
-       if (WARN_ON(!pmu_devices[type]))
-               return -EINVAL;
-       clear_bit_unlock(type, &pmu_lock);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(release_pmu);
-
-static int
-set_irq_affinity(int irq,
-                unsigned int cpu)
-{
-#ifdef CONFIG_SMP
-       int err = irq_set_affinity(irq, cpumask_of(cpu));
-       if (err)
-               pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
-                          irq, cpu);
-       return err;
-#else
-       return -EINVAL;
-#endif
-}
-
-static int
-init_cpu_pmu(void)
-{
-       int i, irqs, err = 0;
-       struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU];
-
-       if (!pdev)
-               return -ENODEV;
-
-       irqs = pdev->num_resources;
-
-       /*
-        * If we have a single PMU interrupt that we can't shift, assume that
-        * we're running on a uniprocessor machine and continue.
-        */
-       if (irqs == 1 && !irq_can_set_affinity(platform_get_irq(pdev, 0)))
-               return 0;
-
-       for (i = 0; i < irqs; ++i) {
-               err = set_irq_affinity(platform_get_irq(pdev, i), i);
-               if (err)
-                       break;
-       }
-
-       return err;
-}
-
-int
-init_pmu(enum arm_pmu_type type)
-{
-       int err = 0;
-
-       switch (type) {
-       case ARM_PMU_DEVICE_CPU:
-               err = init_cpu_pmu();
-               break;
-       default:
-               pr_warning("attempt to initialise PMU of unknown "
-                          "type %d\n", type);
-               err = -EINVAL;
-       }
-
-       return err;
+       clear_bit_unlock(type, pmu_lock);
 }
-EXPORT_SYMBOL_GPL(init_pmu);
index e514c76..6136144 100644 (file)
@@ -820,25 +820,8 @@ static struct machine_desc * __init setup_machine_tags(unsigned int nr)
 
        if (__atags_pointer)
                tags = phys_to_virt(__atags_pointer);
-       else if (mdesc->boot_params) {
-#ifdef CONFIG_MMU
-               /*
-                * We still are executing with a minimal MMU mapping created
-                * with the presumption that the machine default for this
-                * is located in the first MB of RAM.  Anything else will
-                * fault and silently hang the kernel at this point.
-                */
-               if (mdesc->boot_params < PHYS_OFFSET ||
-                   mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
-                       printk(KERN_WARNING
-                              "Default boot params at physical 0x%08lx out of reach\n",
-                              mdesc->boot_params);
-               } else
-#endif
-               {
-                       tags = phys_to_virt(mdesc->boot_params);
-               }
-       }
+       else if (mdesc->atag_offset)
+               tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
 
 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
        /*
index d522b47..6c8e3b5 100644 (file)
@@ -157,7 +157,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc1_clk),
+       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
index e04c5fb..1532b50 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/pm.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
@@ -319,6 +320,7 @@ static void at91sam9g45_poweroff(void)
 static void __init at91sam9g45_map_io(void)
 {
        at91_init_sram(0, AT91SAM9G45_SRAM_BASE, AT91SAM9G45_SRAM_SIZE);
+       init_consistent_dma_size(SZ_4M);
 }
 
 static void __init at91sam9g45_initialize(void)
index 2c611b9..406bb64 100644 (file)
 #define AT91SAM9G45_EHCI_BASE  0x00800000      /* USB Host controller (EHCI) */
 #define AT91SAM9G45_VDEC_BASE  0x00900000      /* Video Decoder Controller */
 
-#define CONSISTENT_DMA_SIZE    SZ_4M
-
 /*
  * DMA peripheral identifiers
  * for hardware handshaking interface
index 15162e4..8848a5b 100644 (file)
@@ -25,9 +25,4 @@
 
 #define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE
 
-/*
- * Maximum DMA memory allowed is 14M
- */
-#define CONSISTENT_DMA_SIZE (SZ_16M - SZ_2M)
-
 #endif
index 0f1c37e..8616876 100644 (file)
@@ -13,6 +13,7 @@
 *****************************************************************************/
 
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
@@ -53,4 +54,6 @@ void __init bcmring_map_io(void)
 {
 
        iotable_init(bcmring_io_desc, ARRAY_SIZE(bcmring_io_desc));
+       /* Maximum DMA memory allowed is 14M */
+       init_consistent_dma_size(14 << 20);
 }
index 4a74b2c..0276091 100644 (file)
@@ -64,7 +64,7 @@ void __init autcpu12_map_io(void)
 
 MACHINE_START(AUTCPU12, "autronix autcpu12")
        /* Maintainer: Thomas Gleixner */
-       .boot_params    = 0xc0020000,
+       .atag_offset    = 0x20000,
        .map_io         = autcpu12_map_io,
        .init_irq       = clps711x_init_irq,
        .timer          = &clps711x_timer,
index 5a1689d..25b3bfd 100644 (file)
@@ -55,7 +55,7 @@ static void __init cdb89712_map_io(void)
 
 MACHINE_START(CDB89712, "Cirrus-CDB89712")
        /* Maintainer: Ray Lehtiniemi */
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = cdb89712_map_io,
        .init_irq       = clps711x_init_irq,
        .timer          = &clps711x_timer,
index 16481cf..1df9ec6 100644 (file)
@@ -56,7 +56,7 @@ static void __init ceiva_map_io(void)
 
 MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
        /* Maintainer: Rob Scott */
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = ceiva_map_io,
        .init_irq       = clps711x_init_irq,
        .timer          = &clps711x_timer,
index 67b5abb..06c8abd 100644 (file)
@@ -37,7 +37,7 @@ fixup_clep7312(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
        /* Maintainer: Nobody */
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x0100,
        .fixup          = fixup_clep7312,
        .map_io         = clps711x_map_io,
        .init_irq       = clps711x_init_irq,
index 98ca5b2..abf522d 100644 (file)
@@ -57,7 +57,7 @@ fixup_edb7211(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
        /* Maintainer: Jon McClintock */
-       .boot_params    = 0xc0020100,   /* 0xc0000000 - 0xc001ffff can be video RAM */
+       .atag_offset    = 0x20100,      /* 0xc0000000 - 0xc001ffff can be video RAM */
        .fixup          = fixup_edb7211,
        .map_io         = edb7211_map_io,
        .reserve        = edb7211_reserve,
index b1cb479..b6f7d86 100644 (file)
@@ -75,7 +75,6 @@ fortunet_fixup(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(FORTUNET, "ARM-FortuNet")
        /* Maintainer: FortuNet Inc. */
-       .boot_params    = 0x00000000,
        .fixup          = fortunet_fixup,
        .map_io         = clps711x_map_io,
        .init_irq       = clps711x_init_irq,
index cefbce0..e7f75ae 100644 (file)
@@ -89,7 +89,7 @@ static void __init p720t_map_io(void)
 
 MACHINE_START(P720T, "ARM-Prospector720T")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .fixup          = fixup_p720t,
        .map_io         = p720t_map_io,
        .init_irq       = clps711x_init_irq,
index 3e7d149..55f7b4b 100644 (file)
@@ -197,7 +197,7 @@ static void __init cns3420_map_io(void)
 }
 
 MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = cns3420_map_io,
        .init_irq       = cns3xxx_init_irq,
        .timer          = &cns3xxx_timer,
index 6bd83ed..d87bfc3 100644 (file)
@@ -8,7 +8,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <mach/hardware.h>
 #include <asm/hardware/entry-macro-gic.S>
 
                .macro  disable_fiq
index 58bb03a..4f16c9b 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/io.h>
 #include <asm/proc-fns.h>
-#include <mach/hardware.h>
 
 static inline void arch_idle(void)
 {
index de8ead9..a91b605 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
 #include <mach/cns3xxx.h>
 
 #define AMBA_UART_DR(base)     (*(volatile unsigned char *)((base) + 0x00))
index 06fd25d..0f8fca4 100644 (file)
@@ -49,7 +49,7 @@ static struct cns3xxx_pcie *sysdata_to_cnspci(void *sysdata)
        return &cns3xxx_pcie[root->domain];
 }
 
-static struct cns3xxx_pcie *pdev_to_cnspci(struct pci_dev *dev)
+static struct cns3xxx_pcie *pdev_to_cnspci(const struct pci_dev *dev)
 {
        return sysdata_to_cnspci(dev->sysdata);
 }
index 84fd786..26d94c0 100644 (file)
@@ -676,7 +676,7 @@ static void __init da830_evm_map_io(void)
 }
 
 MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
-       .boot_params    = (DA8XX_DDR_BASE + 0x100),
+       .atag_offset    = 0x100,
        .map_io         = da830_evm_map_io,
        .init_irq       = cp_intc_init,
        .timer          = &davinci_timer,
index bd53945..6e41cb5 100644 (file)
@@ -115,6 +115,32 @@ static struct spi_board_info da850evm_spi_info[] = {
        },
 };
 
+#ifdef CONFIG_MTD
+static void da850_evm_m25p80_notify_add(struct mtd_info *mtd)
+{
+       char *mac_addr = davinci_soc_info.emac_pdata->mac_addr;
+       size_t retlen;
+
+       if (!strcmp(mtd->name, "MAC-Address")) {
+               mtd->read(mtd, 0, ETH_ALEN, &retlen, mac_addr);
+               if (retlen == ETH_ALEN)
+                       pr_info("Read MAC addr from SPI Flash: %pM\n",
+                               mac_addr);
+       }
+}
+
+static struct mtd_notifier da850evm_spi_notifier = {
+       .add    = da850_evm_m25p80_notify_add,
+};
+
+static void da850_evm_setup_mac_addr(void)
+{
+       register_mtd_user(&da850evm_spi_notifier);
+}
+#else
+static void da850_evm_setup_mac_addr(void) { }
+#endif
+
 static struct mtd_partition da850_evm_norflash_partition[] = {
        {
                .name           = "bootloaders + env",
@@ -1244,6 +1270,8 @@ static __init void da850_evm_init(void)
        if (ret)
                pr_warning("da850_evm_init: sata registration failed: %d\n",
                                ret);
+
+       da850_evm_setup_mac_addr();
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
@@ -1263,7 +1291,7 @@ static void __init da850_evm_map_io(void)
 }
 
 MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
-       .boot_params    = (DA8XX_DDR_BASE + 0x100),
+       .atag_offset    = 0x100,
        .map_io         = da850_evm_map_io,
        .init_irq       = cp_intc_init,
        .timer          = &davinci_timer,
index 241a6bd..6556628 100644 (file)
@@ -351,7 +351,7 @@ static __init void dm355_evm_init(void)
 }
 
 MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
-       .boot_params  = (0x80000100),
+       .atag_offset  = 0x100,
        .map_io       = dm355_evm_map_io,
        .init_irq     = davinci_irq_init,
        .timer        = &davinci_timer,
index bee284c..b307470 100644 (file)
@@ -270,7 +270,7 @@ static __init void dm355_leopard_init(void)
 }
 
 MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
-       .boot_params  = (0x80000100),
+       .atag_offset  = 0x100,
        .map_io       = dm355_leopard_map_io,
        .init_irq     = davinci_irq_init,
        .timer        = &davinci_timer,
index 9818f21..04c43ab 100644 (file)
@@ -612,7 +612,7 @@ static __init void dm365_evm_init(void)
 }
 
 MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
-       .boot_params    = (0x80000100),
+       .atag_offset    = 0x100,
        .map_io         = dm365_evm_map_io,
        .init_irq       = davinci_irq_init,
        .timer          = &davinci_timer,
index 95607a1..a005e76 100644 (file)
@@ -712,7 +712,7 @@ static __init void davinci_evm_init(void)
 
 MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
        /* Maintainer: MontaVista Software <source@mvista.com> */
-       .boot_params  = (DAVINCI_DDR_BASE + 0x100),
+       .atag_offset  = 0x100,
        .map_io       = davinci_evm_map_io,
        .init_irq     = davinci_irq_init,
        .timer        = &davinci_timer,
index 993a314..337c45e 100644 (file)
@@ -792,7 +792,7 @@ static __init void evm_init(void)
 }
 
 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
-       .boot_params  = (0x80000100),
+       .atag_offset  = 0x100,
        .map_io       = davinci_map_io,
        .init_irq     = davinci_irq_init,
        .timer        = &davinci_timer,
@@ -801,7 +801,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
 MACHINE_END
 
 MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
-       .boot_params  = (0x80000100),
+       .atag_offset  = 0x100,
        .map_io       = davinci_map_io,
        .init_irq     = davinci_irq_init,
        .timer        = &davinci_timer,
index c278226..6efc84c 100644 (file)
@@ -566,7 +566,7 @@ static void __init mityomapl138_map_io(void)
 }
 
 MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
-       .boot_params    = (DA8XX_DDR_BASE + 0x100),
+       .atag_offset    = 0x100,
        .map_io         = mityomapl138_map_io,
        .init_irq       = cp_intc_init,
        .timer          = &davinci_timer,
index d60a800..38d6f64 100644 (file)
@@ -272,7 +272,7 @@ static __init void davinci_ntosd2_init(void)
 
 MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
        /* Maintainer: Neuros Technologies <neuros@groups.google.com> */
-       .boot_params    = (DAVINCI_DDR_BASE + 0x100),
+       .atag_offset    = 0x100,
        .map_io          = davinci_ntosd2_map_io,
        .init_irq       = davinci_irq_init,
        .timer          = &davinci_timer,
index 237332a..c6701e4 100644 (file)
@@ -338,7 +338,7 @@ static void __init omapl138_hawk_map_io(void)
 }
 
 MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
-       .boot_params    = (DA8XX_DDR_BASE + 0x100),
+       .atag_offset    = 0x100,
        .map_io         = omapl138_hawk_map_io,
        .init_irq       = cp_intc_init,
        .timer          = &davinci_timer,
index 5f4385c..5dd4da9 100644 (file)
@@ -151,7 +151,7 @@ static __init void davinci_sffsdr_init(void)
 
 MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
        /* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */
-       .boot_params  = (DAVINCI_DDR_BASE + 0x100),
+       .atag_offset  = 0x100,
        .map_io       = davinci_sffsdr_map_io,
        .init_irq     = davinci_irq_init,
        .timer        = &davinci_timer,
index 7828920..90ee7b5 100644 (file)
@@ -277,7 +277,7 @@ console_initcall(tnetv107x_evm_console_init);
 #endif
 
 MACHINE_START(TNETV107X, "TNETV107X EVM")
-       .boot_params    = (TNETV107X_DDR_BASE + 0x100),
+       .atag_offset    = 0x100,
        .map_io         = tnetv107x_init,
        .init_irq       = cp_intc_init,
        .timer          = &davinci_timer,
index 1d25573..865ffe5 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/etherdevice.h>
 #include <linux/davinci_emac.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/tlb.h>
 #include <asm/mach/map.h>
@@ -86,6 +87,8 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info)
                iotable_init(davinci_soc_info.io_desc,
                                davinci_soc_info.io_desc_num);
 
+       init_consistent_dma_size(14 << 20);
+
        /*
         * Normally devicemaps_init() would flush caches and tlb after
         * mdesc->map_io(), but we must also do it here because of the CPU
index 7873194..885d233 100644 (file)
@@ -36,9 +36,4 @@
 #define DDR2_MCLKSTOPEN_BIT    BIT(30)
 #define DDR2_LPMODEN_BIT       BIT(31)
 
-/*
- * Increase size of DMA-consistent memory region
- */
-#define CONSISTENT_DMA_SIZE (14<<20)
-
 #endif /* __ASM_ARCH_MEMORY_H */
index 47fd0bc..fa59c09 100644 (file)
 #define PSC_STATE_DISABLE      2
 #define PSC_STATE_ENABLE       3
 
-#define MDSTAT_STATE_MASK      0x1f
+#define MDSTAT_STATE_MASK      0x3f
 #define MDCTL_FORCE            BIT(31)
 
 #ifndef __ASSEMBLER__
index fb5e72b..5f1e045 100644 (file)
@@ -217,7 +217,11 @@ ddr2clk_stop_done:
 ENDPROC(davinci_ddr_psc_config)
 
 CACHE_FLUSH:
-       .word   arm926_flush_kern_cache_all
+#ifdef CONFIG_CPU_V6
+       .word   v6_flush_kern_cache_all
+#else
+       .word   arm926_flush_kern_cache_all
+#endif
 
 ENTRY(davinci_cpu_suspend_sz)
        .word   . - davinci_cpu_suspend
index 03e11f9..c8a406f 100644 (file)
@@ -87,7 +87,7 @@ static void __init cm_a510_init(void)
 }
 
 MACHINE_START(CM_A510, "Compulab CM-A510 Board")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = cm_a510_init,
        .map_io         = dove_map_io,
        .init_early     = dove_init_early,
index 2ac34ec..11ea34e 100644 (file)
@@ -94,7 +94,7 @@ static void __init dove_db_init(void)
 }
 
 MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = dove_db_init,
        .map_io         = dove_map_io,
        .init_early     = dove_init_early,
index 087bc77..d0ce8ab 100644 (file)
@@ -280,7 +280,7 @@ arch_initcall(ebsa110_init);
 
 MACHINE_START(EBSA110, "EBSA110")
        /* Maintainer: Russell King */
-       .boot_params    = 0x00000400,
+       .atag_offset    = 0x400,
        .reserve_lp0    = 1,
        .reserve_lp2    = 1,
        .soft_reboot    = 1,
index 61b98ce..0713448 100644 (file)
@@ -33,7 +33,7 @@ static void __init adssphere_init_machine(void)
 
 MACHINE_START(ADSSPHERE, "ADS Sphere board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
index 9969bb1..257175e 100644 (file)
@@ -240,7 +240,7 @@ static void __init edb93xx_init_machine(void)
 #ifdef CONFIG_MACH_EDB9301
 MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
        /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -251,7 +251,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9302
 MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
        /* Maintainer: George Kashperko <george@chas.com.ua> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -262,7 +262,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9302A
 MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -273,7 +273,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9307
 MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
        /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -284,7 +284,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9307A
 MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
        /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-       .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -295,7 +295,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9312
 MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
        /* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -306,7 +306,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9315
 MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -317,7 +317,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_EDB9315A
 MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
index 9bd3152..45ee205 100644 (file)
@@ -33,7 +33,7 @@ static void __init gesbc9312_init_machine(void)
 
 MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
index 7adea62..e72f736 100644 (file)
@@ -77,7 +77,7 @@ static void __init micro9_init_machine(void)
 #ifdef CONFIG_MACH_MICRO9H
 MACHINE_START(MICRO9, "Contec Micro9-High")
        /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -88,7 +88,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9M
 MACHINE_START(MICRO9M, "Contec Micro9-Mid")
        /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -99,7 +99,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9L
 MACHINE_START(MICRO9L, "Contec Micro9-Lite")
        /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
@@ -110,7 +110,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_MICRO9S
 MACHINE_START(MICRO9S, "Contec Micro9-Slim")
        /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
index 8392e95..238bc60 100644 (file)
@@ -65,8 +65,8 @@ static void __init simone_init_machine(void)
 }
 
 MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
-/* Maintainer: Ryan Mallon */
-       .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
+       /* Maintainer: Ryan Mallon */
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
index 2e9c614..3bdf3a2 100644 (file)
@@ -163,7 +163,7 @@ static void __init snappercl15_init_machine(void)
 
 MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
        /* Maintainer: Ryan Mallon */
-       .boot_params    = EP93XX_SDCE0_PHYS_BASE + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
index c2d2cf4..1ade3c3 100644 (file)
@@ -257,7 +257,7 @@ static void __init ts72xx_init_machine(void)
 
 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ts72xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
index 851dea0..1561b03 100644 (file)
@@ -520,7 +520,7 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 21),
        }, {
                .name           = "ac97",
-               .id             = -1,
+               .devname        = "samsung-ac97",
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 27),
        }, {
index 2d8a40c..746d6fc 100644 (file)
 #include <plat/exynos4.h>
 #include <plat/adc-core.h>
 #include <plat/sdhci.h>
-#include <plat/devs.h>
 #include <plat/fb-core.h>
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
+#include <plat/reset.h>
 
 #include <mach/regs-irq.h>
+#include <mach/regs-pmu.h>
 
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
                         unsigned int irq_start);
@@ -128,6 +129,11 @@ static void exynos4_idle(void)
        local_irq_enable();
 }
 
+static void exynos4_sw_reset(void)
+{
+       __raw_writel(0x1, S5P_SWRESET);
+}
+
 /*
  * exynos4_map_io
  *
@@ -241,5 +247,8 @@ int __init exynos4_init(void)
        /* set idle function */
        pm_idle = exynos4_idle;
 
+       /* set sw_reset function */
+       s5p_reset_hook = exynos4_sw_reset;
+
        return sysdev_register(&exynos4_sysdev);
 }
index 934d2a4..f8952f8 100644 (file)
@@ -80,9 +80,8 @@
 #define IRQ_HSMMC3             IRQ_SPI(76)
 #define IRQ_DWMCI              IRQ_SPI(77)
 
-#define IRQ_MIPICSI0           IRQ_SPI(78)
-
-#define IRQ_MIPICSI1           IRQ_SPI(80)
+#define IRQ_MIPI_CSIS0         IRQ_SPI(78)
+#define IRQ_MIPI_CSIS1         IRQ_SPI(80)
 
 #define IRQ_ONENAND_AUDI       IRQ_SPI(82)
 #define IRQ_ROTATOR            IRQ_SPI(83)
index fa49bbb..cdf9b47 100644 (file)
@@ -29,6 +29,8 @@
 #define S5P_USE_STANDBY_WFE1                   (1 << 25)
 #define S5P_USE_MASK                           ((0x3 << 16) | (0x3 << 24))
 
+#define S5P_SWRESET                            S5P_PMUREG(0x0400)
+
 #define S5P_WAKEUP_STAT                                S5P_PMUREG(0x0600)
 #define S5P_EINT_WAKEUP_MASK                   S5P_PMUREG(0x0604)
 #define S5P_WAKEUP_MASK                                S5P_PMUREG(0x0608)
index 9d87d2a..badb8c6 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <mach/regs-gpio.h>
 
+#include <asm/mach/irq.h>
+
 static DEFINE_SPINLOCK(eint_lock);
 
 static unsigned int eint0_15_data[16];
@@ -184,8 +186,11 @@ static inline void exynos4_irq_demux_eint(unsigned int start)
 
 static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
 {
+       struct irq_chip *chip = irq_get_chip(irq);
+       chained_irq_enter(chip, desc);
        exynos4_irq_demux_eint(IRQ_EINT(16));
        exynos4_irq_demux_eint(IRQ_EINT(24));
+       chained_irq_exit(chip, desc);
 }
 
 static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
@@ -193,6 +198,7 @@ static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
        u32 *irq_data = irq_get_handler_data(irq);
        struct irq_chip *chip = irq_get_chip(irq);
 
+       chained_irq_enter(chip, desc);
        chip->irq_mask(&desc->irq_data);
 
        if (chip->irq_ack)
@@ -201,6 +207,7 @@ static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
        generic_handle_irq(*irq_data);
 
        chip->irq_unmask(&desc->irq_data);
+       chained_irq_exit(chip, desc);
 }
 
 int __init exynos4_init_irq_eint(void)
index b482c62..f0ca6c1 100644 (file)
@@ -207,7 +207,7 @@ static void __init armlex4210_machine_init(void)
 
 MACHINE_START(ARMLEX4210, "ARMLEX4210")
        /* Maintainer: Alim Akhtar <alim.akhtar@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = exynos4_init_irq,
        .map_io         = armlex4210_map_io,
        .init_machine   = armlex4210_machine_init,
index 43be71b..6e05368 100644 (file)
@@ -1152,7 +1152,7 @@ static void __init nuri_machine_init(void)
 
 MACHINE_START(NURI, "NURI")
        /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = exynos4_init_irq,
        .map_io         = nuri_map_io,
        .init_machine   = nuri_machine_init,
index a7c65e0..b24ddd7 100644 (file)
@@ -301,7 +301,7 @@ static void __init smdkc210_machine_init(void)
 
 MACHINE_START(SMDKC210, "SMDKC210")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = exynos4_init_irq,
        .map_io         = smdkc210_map_io,
        .init_machine   = smdkc210_machine_init,
index ea41495..d90fcdd 100644 (file)
@@ -255,7 +255,7 @@ static void __init smdkv310_machine_init(void)
 MACHINE_START(SMDKV310, "SMDKV310")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
        /* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = exynos4_init_irq,
        .map_io         = smdkv310_map_io,
        .init_machine   = smdkv310_machine_init,
index 0e280d1..2aac6f7 100644 (file)
@@ -79,7 +79,7 @@ static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
 };
 
 static struct regulator_consumer_supply max8952_consumer =
-       REGULATOR_SUPPLY("vddarm", NULL);
+       REGULATOR_SUPPLY("vdd_arm", NULL);
 
 static struct max8952_platform_data universal_max8952_pdata __initdata = {
        .gpio_vid0      = EXYNOS4_GPX0(3),
@@ -105,7 +105,7 @@ static struct max8952_platform_data universal_max8952_pdata __initdata = {
 };
 
 static struct regulator_consumer_supply lp3974_buck1_consumer =
-       REGULATOR_SUPPLY("vddint", NULL);
+       REGULATOR_SUPPLY("vdd_int", NULL);
 
 static struct regulator_consumer_supply lp3974_buck2_consumer =
        REGULATOR_SUPPLY("vddg3d", NULL);
@@ -762,7 +762,7 @@ static void __init universal_machine_init(void)
 
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
        /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = exynos4_init_irq,
        .map_io         = universal_map_io,
        .init_machine   = universal_machine_init,
index 0883c1b..39aca04 100644 (file)
@@ -82,7 +82,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
 
        rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
        writel(rstcon, EXYNOS4_RSTCON);
-       udelay(50);
+       udelay(80);
 
        clk_disable(otg_clk);
        clk_put(otg_clk);
index 5b1a8db..a3da5d1 100644 (file)
@@ -86,7 +86,7 @@ fixup_cats(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(CATS, "Chalice-CATS")
        /* Maintainer: Philip Blundell */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .soft_reboot    = 1,
        .fixup          = fixup_cats,
        .map_io         = footbridge_map_io,
index 1331fff..18c32a5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <video/vga.h>
 
 #include <asm/irq.h>
 #include <asm/system.h>
index 2ef69ff..012210c 100644 (file)
@@ -15,7 +15,7 @@
 
 MACHINE_START(EBSA285, "EBSA285")
        /* Maintainer: Russell King */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .video_start    = 0x000a0000,
        .video_end      = 0x000bffff,
        .map_io         = footbridge_map_io,
index 06e514f..d8c1c92 100644 (file)
@@ -648,7 +648,7 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags,
 
 MACHINE_START(NETWINDER, "Rebel-NetWinder")
        /* Maintainer: Russell King/Rebel.com */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .video_start    = 0x000a0000,
        .video_end      = 0x000bffff,
        .reserve_lp0    = 1,
index 3285e91..f41dba3 100644 (file)
@@ -15,7 +15,7 @@
 
 MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
        /* Maintainer: Jamey Hicks / George France */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = footbridge_map_io,
        .init_irq       = footbridge_init_irq,
        .timer          = &footbridge_timer,
index 0cf7a07..5927d3c 100644 (file)
@@ -102,7 +102,7 @@ static void __init ib4220b_init(void)
 }
 
 MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
-       .boot_params    = 0x100,
+       .atag_offset    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
        .timer          = &ib4220b_timer,
index 4fa09af..cd7437a 100644 (file)
@@ -86,7 +86,7 @@ static void __init rut1xx_init(void)
 }
 
 MACHINE_START(RUT100, "Teltonika RUT100")
-       .boot_params    = 0x100,
+       .atag_offset    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
        .timer          = &rut1xx_timer,
index 88cc422..a367880 100644 (file)
@@ -129,7 +129,7 @@ static void __init wbd111_init(void)
 }
 
 MACHINE_START(WBD111, "Wiliboard WBD-111")
-       .boot_params    = 0x100,
+       .atag_offset    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
        .timer          = &wbd111_timer,
index 3a22034..f382811 100644 (file)
@@ -129,7 +129,7 @@ static void __init wbd222_init(void)
 }
 
 MACHINE_START(WBD222, "Wiliboard WBD-222")
-       .boot_params    = 0x100,
+       .atag_offset    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
        .timer          = &wbd222_timer,
index 65f1bea..9886f19 100644 (file)
@@ -29,7 +29,7 @@
 
 MACHINE_START(H7201, "Hynix GMS30C7201")
        /* Maintainer: Robert Schwebel, Pengutronix */
-       .boot_params    = 0xc0001000,
+       .atag_offset    = 0x1000,
        .map_io         = h720x_map_io,
        .init_irq       = h720x_init_irq,
        .timer          = &h7201_timer,
index 884584a..284a134 100644 (file)
@@ -71,7 +71,7 @@ static void __init init_eval_h7202(void)
 
 MACHINE_START(H7202, "Hynix HMS30C7202")
        /* Maintainer: Robert Schwebel, Pengutronix */
-       .boot_params    = 0x40000100,
+       .atag_offset    = 0x100,
        .map_io         = h720x_map_io,
        .init_irq       = h7202_init_irq,
        .timer          = &h7202_timer,
index ede2710..2152590 100644 (file)
@@ -558,7 +558,7 @@ static struct sys_timer armadillo5x0_timer = {
 
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
        /* Maintainer: Alberto Panizzo  */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx31_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
index f851fe9..b1ec2cf 100644 (file)
@@ -311,7 +311,7 @@ static struct sys_timer eukrea_cpuimx27_timer = {
 };
 
 MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27")
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index 4bd083b..470b654 100644 (file)
@@ -194,7 +194,7 @@ struct sys_timer eukrea_cpuimx35_timer = {
 
 MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35")
        /* Maintainer: Eukrea Electromatique */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx35_map_io,
        .init_early = imx35_init_early,
        .init_irq = mx35_init_irq,
index 2442d5d..9163318 100644 (file)
@@ -163,7 +163,7 @@ static struct sys_timer eukrea_cpuimx25_timer = {
 
 MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
        /* Maintainer: Eukrea Electromatique */
-       .boot_params = MX25_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx25_map_io,
        .init_early = imx25_init_early,
        .init_irq = mx25_init_irq,
index 6778f81..22306ce 100644 (file)
@@ -275,7 +275,7 @@ static struct sys_timer visstrim_m10_timer = {
 };
 
 MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index 272f793..8da48b3 100644 (file)
@@ -71,7 +71,7 @@ static struct sys_timer mx27ipcam_timer = {
 
 MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
        /* maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index d81a769..21a14a2 100644 (file)
@@ -77,7 +77,7 @@ static struct sys_timer mx27lite_timer = {
 };
 
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index e472a1d..7c20e9e 100644 (file)
@@ -271,7 +271,7 @@ static struct sys_timer kzm_timer = {
 };
 
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = kzm_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
index 5cd8bee..530ea08 100644 (file)
@@ -145,7 +145,7 @@ struct sys_timer mx1ads_timer = {
 
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
        /* Maintainer: Sascha Hauer, Pengutronix */
-       .boot_params = MX1_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx1_map_io,
        .init_early = imx1_init_early,
        .init_irq = mx1_init_irq,
@@ -154,7 +154,7 @@ MACHINE_START(MX1ADS, "Freescale MX1ADS")
 MACHINE_END
 
 MACHINE_START(MXLADS, "Freescale MXLADS")
-       .boot_params = MX1_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx1_map_io,
        .init_early = imx1_init_early,
        .init_irq = mx1_init_irq,
index d389ecf..e56828d 100644 (file)
@@ -305,7 +305,7 @@ static struct sys_timer mx21ads_timer = {
 
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
        /* maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX21_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx21ads_map_io,
        .init_early = imx21_init_early,
        .init_irq = mx21_init_irq,
index 7f66a91..dd25ee8 100644 (file)
@@ -253,7 +253,7 @@ static struct sys_timer mx25pdk_timer = {
 
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX25_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx25_map_io,
        .init_early = imx25_init_early,
        .init_irq = mx25_init_irq,
index 6fa6934..2eafbac 100644 (file)
@@ -421,7 +421,7 @@ static struct sys_timer mx27pdk_timer = {
 
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
        /* maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index fc26ed7..efe6109 100644 (file)
@@ -345,7 +345,7 @@ static void __init mx27ads_map_io(void)
 
 MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
        /* maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27ads_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index c20be75..589066f 100644 (file)
@@ -764,7 +764,7 @@ static void __init mx31_3ds_reserve(void)
 
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx31_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
index 29ca890..910c456 100644 (file)
@@ -535,7 +535,7 @@ static struct sys_timer mx31ads_timer = {
 
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx31ads_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31ads_init_irq,
index 126913a..e92eaf9 100644 (file)
@@ -295,7 +295,7 @@ static struct sys_timer mx31lilly_timer = {
 };
 
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx31_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
index 4b47fd9..5242cb7 100644 (file)
@@ -280,7 +280,7 @@ struct sys_timer mx31lite_timer = {
 
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx31lite_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
index b358383..1d01ef2 100644 (file)
@@ -567,7 +567,7 @@ static void __init mx31moboard_reserve(void)
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
        /* Maintainer: Valentin Longchamp, EPFL Mobots group */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .reserve = mx31moboard_reserve,
        .map_io = mx31_map_io,
        .init_early = imx31_init_early,
index b3b9bd8..f2a873d 100644 (file)
@@ -217,7 +217,7 @@ struct sys_timer mx35pdk_timer = {
 
 MACHINE_START(MX35_3DS, "Freescale MX35PDK")
        /* Maintainer: Freescale Semiconductor, Inc */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx35_map_io,
        .init_early = imx35_init_early,
        .init_irq = mx35_init_irq,
index c85876f..5ec3989 100644 (file)
@@ -267,7 +267,7 @@ static struct sys_timer mxt_td60_timer = {
 
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
        /* maintainer: Maxtrack Industrial */
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index 71083aa..0f6bd11 100644 (file)
@@ -435,7 +435,7 @@ static struct sys_timer pca100_timer = {
 };
 
 MACHINE_START(PCA100, "phyCARD-i.MX27")
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index f45b7cd..186d4eb 100644 (file)
@@ -688,7 +688,7 @@ static void __init pcm037_reserve(void)
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
        /* Maintainer: Pengutronix */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .reserve = pcm037_reserve,
        .map_io = mx31_map_io,
        .init_early = imx31_init_early,
index 2d6a64b..091bcf8 100644 (file)
@@ -349,7 +349,7 @@ static struct sys_timer pcm038_timer = {
 };
 
 MACHINE_START(PCM038, "phyCORE-i.MX27")
-       .boot_params = MX27_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
index 660ec3e..0a4d31d 100644 (file)
@@ -418,7 +418,7 @@ struct sys_timer pcm043_timer = {
 
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
        /* Maintainer: Pengutronix */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx35_map_io,
        .init_early = imx35_init_early,
        .init_irq = mx35_init_irq,
index 3626f48..9e11359 100644 (file)
@@ -262,7 +262,7 @@ static struct sys_timer qong_timer = {
 
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
        /* Maintainer: DENX Software Engineering GmbH */
-       .boot_params = MX3x_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx31_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
index db2d604..85d3284 100644 (file)
@@ -137,7 +137,7 @@ static struct sys_timer scb9328_timer = {
 
 MACHINE_START(SCB9328, "Synertronixx scb9328")
        /* Sascha Hauer */
-       .boot_params = 0x08000100,
+       .atag_offset = 100,
        .map_io = mx1_map_io,
        .init_early = imx1_init_early,
        .init_irq = mx1_init_irq,
index 2fbbdd5..b19ae18 100644 (file)
@@ -337,15 +337,15 @@ static unsigned long timer_reload;
 static void integrator_clocksource_init(u32 khz)
 {
        void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
-       u32 ctrl = TIMER_CTRL_ENABLE;
+       u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
 
        if (khz >= 1500) {
                khz /= 16;
-               ctrl = TIMER_CTRL_DIV16;
+               ctrl |= TIMER_CTRL_DIV16;
        }
 
-       writel(ctrl, base + TIMER_CTRL);
        writel(0xffff, base + TIMER_LOAD);
+       writel(ctrl, base + TIMER_CTRL);
 
        clocksource_mmio_init(base + TIMER_VALUE, "timer2",
                khz * 1000, 200, 16, clocksource_mmio_readl_down);
@@ -457,7 +457,7 @@ static struct sys_timer ap_timer = {
 
 MACHINE_START(INTEGRATOR, "ARM-Integrator")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .reserve        = integrator_reserve,
        .map_io         = ap_map_io,
        .init_early     = integrator_init_early,
index 4eb03ab..5de49c3 100644 (file)
@@ -492,7 +492,7 @@ static struct sys_timer cp_timer = {
 
 MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .reserve        = integrator_reserve,
        .map_io         = intcp_map_io,
        .init_early     = intcp_init_early,
index 23dfaff..4cf2cc4 100644 (file)
@@ -91,7 +91,7 @@ static struct sys_timer iq81340mc_timer = {
 
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
        /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = iop13xx_map_io,
        .init_irq       = iop13xx_init_irq,
        .timer          = &iq81340mc_timer,
index df3492a..cd9e274 100644 (file)
@@ -93,7 +93,7 @@ static struct sys_timer iq81340sc_timer = {
 
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
        /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = iop13xx_map_io,
        .init_irq       = iop13xx_init_irq,
        .timer          = &iq81340sc_timer,
index 6cbffbf..4325055 100644 (file)
@@ -203,7 +203,7 @@ static void __init em7210_init_machine(void)
 }
 
 MACHINE_START(EM7210, "Lanner EM7210")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = em7210_map_io,
        .init_irq       = iop32x_init_irq,
        .timer          = &em7210_timer,
index ceef5d4..0edc880 100644 (file)
@@ -207,7 +207,7 @@ static void __init glantank_init_machine(void)
 
 MACHINE_START(GLANTANK, "GLAN Tank")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = glantank_map_io,
        .init_irq       = iop32x_init_irq,
        .timer          = &glantank_timer,
index 3a62514..9e7aacc 100644 (file)
@@ -313,7 +313,7 @@ __setup("force_ep80219", force_ep80219_setup);
 
 MACHINE_START(IQ31244, "Intel IQ31244")
        /* Maintainer: Intel Corp. */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = iq31244_map_io,
        .init_irq       = iop32x_init_irq,
        .timer          = &iq31244_timer,
@@ -327,7 +327,7 @@ MACHINE_END
  */
 MACHINE_START(EP80219, "Intel EP80219")
        /* Maintainer: Intel Corp. */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = iq31244_map_io,
        .init_irq       = iop32x_init_irq,
        .timer          = &iq31244_timer,
index 35b7e69..53ea86f 100644 (file)
@@ -186,7 +186,7 @@ static void __init iq80321_init_machine(void)
 
 MACHINE_START(IQ80321, "Intel IQ80321")
        /* Maintainer: Intel Corp. */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = iq80321_map_io,
        .init_irq       = iop32x_init_irq,
        .timer          = &iq80321_timer,
index 1a374ea..d726927 100644 (file)
@@ -327,7 +327,7 @@ static void __init n2100_init_machine(void)
 
 MACHINE_START(N2100, "Thecus N2100")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = n2100_map_io,
        .init_irq       = iop32x_init_irq,
        .timer          = &n2100_timer,
index 637c027..9e14ccc 100644 (file)
@@ -141,7 +141,7 @@ static void __init iq80331_init_machine(void)
 
 MACHINE_START(IQ80331, "Intel IQ80331")
        /* Maintainer: Intel Corp. */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = iop3xx_map_io,
        .init_irq       = iop33x_init_irq,
        .timer          = &iq80331_timer,
index 90a0436..09c899a 100644 (file)
@@ -141,7 +141,7 @@ static void __init iq80332_init_machine(void)
 
 MACHINE_START(IQ80332, "Intel IQ80332")
        /* Maintainer: Intel Corp. */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = iop3xx_map_io,
        .init_irq       = iop33x_init_irq,
        .timer          = &iq80332_timer,
index 62c60ad..af99945 100644 (file)
@@ -254,7 +254,7 @@ static void __init enp2611_init_machine(void)
 
 MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = enp2611_map_io,
        .init_irq       = ixp2000_init_irq,
        .timer          = &enp2611_timer,
index 5bad1a8..f7dfd97 100644 (file)
@@ -171,7 +171,7 @@ void __init ixdp2400_init_irq(void)
 
 MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = ixdp2x00_map_io,
        .init_irq       = ixdp2400_init_irq,
        .timer          = &ixdp2400_timer,
index 3d3cef8..d33bcac 100644 (file)
@@ -286,7 +286,7 @@ void __init ixdp2800_init_irq(void)
 
 MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = ixdp2x00_map_io,
        .init_irq       = ixdp2800_init_irq,
        .timer          = &ixdp2800_timer,
index be2a254..61a2867 100644 (file)
@@ -417,7 +417,7 @@ static void __init ixdp2x01_init_machine(void)
 #ifdef CONFIG_ARCH_IXDP2401
 MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = ixdp2x01_map_io,
        .init_irq       = ixdp2x01_init_irq,
        .timer          = &ixdp2x01_timer,
@@ -428,7 +428,7 @@ MACHINE_END
 #ifdef CONFIG_ARCH_IXDP2801
 MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = ixdp2x01_map_io,
        .init_irq       = ixdp2x01_init_irq,
        .timer          = &ixdp2x01_timer,
@@ -441,7 +441,7 @@ MACHINE_END
  */
 MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = ixdp2x01_map_io,
        .init_irq       = ixdp2x01_init_irq,
        .timer          = &ixdp2x01_timer,
index e25e5fe..30dd316 100644 (file)
@@ -88,6 +88,6 @@ MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
        .map_io         = ixp23xx_map_io,
        .init_irq       = ixp23xx_init_irq,
        .timer          = &ixp23xx_timer,
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = espresso_init,
 MACHINE_END
index ec028e3..b3a57e0 100644 (file)
@@ -331,6 +331,6 @@ MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
        .map_io         = ixdp2351_map_io,
        .init_irq       = ixdp2351_init_irq,
        .timer          = &ixp23xx_timer,
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = ixdp2351_init,
 MACHINE_END
index 844551d..8f4dcbb 100644 (file)
@@ -175,6 +175,6 @@ MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
        .map_io         = ixp23xx_map_io,
        .init_irq       = ixp23xx_init_irq,
        .timer          = &ixp23xx_timer,
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = roadrunner_init,
 MACHINE_END
index ee19c1d..37609a2 100644 (file)
@@ -167,7 +167,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = avila_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
@@ -185,7 +185,7 @@ MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = avila_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index e24564b..81dfec3 100644 (file)
@@ -112,7 +112,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = coyote_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
@@ -130,7 +130,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = coyote_init,
 MACHINE_END
 #endif
index 03e5451..71607a7 100644 (file)
@@ -279,7 +279,7 @@ static void __init dsmg600_init(void)
 
 MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
        /* Maintainer: www.nslu2-linux.org */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &dsmg600_timer,
index 23a8b36..a9540cd 100644 (file)
@@ -273,7 +273,7 @@ MACHINE_START(FSG, "Freecom FSG-3")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = fsg_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index d4f851b..d69d1b0 100644 (file)
@@ -99,7 +99,7 @@ MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = gateway7001_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index 7548d9a..bf6678d 100644 (file)
@@ -499,7 +499,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = gmlr_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index 3790dff..aa029fc 100644 (file)
@@ -167,7 +167,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = gtwx5715_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index 6a29279..f235f82 100644 (file)
@@ -256,7 +256,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = ixdp425_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
@@ -270,7 +270,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = ixdp425_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
@@ -284,7 +284,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = ixdp425_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
@@ -298,7 +298,7 @@ MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = ixdp425_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index afb5187..9f46692 100644 (file)
@@ -314,7 +314,7 @@ static void __init nas100d_init(void)
 
 MACHINE_START(NAS100D, "Iomega NAS 100d")
        /* Maintainer: www.nslu2-linux.org */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
index 69e40f2..3676fbf 100644 (file)
@@ -300,7 +300,7 @@ static void __init nslu2_init(void)
 
 MACHINE_START(NSLU2, "Linksys NSLU2")
        /* Maintainer: www.nslu2-linux.org */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &nslu2_timer,
index 045336c..27e469e 100644 (file)
@@ -239,7 +239,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = vulcan_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index 40b9fad..b14144b 100644 (file)
@@ -100,7 +100,7 @@ MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
        .map_io         = ixp4xx_map_io,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
+       .atag_offset    = 0x100,
        .init_machine   = wg302v2_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index 043cfd5..f457e07 100644 (file)
@@ -221,7 +221,7 @@ static void __init d2net_v2_init(void)
 }
 
 MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = d2net_v2_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index bff04e0..ff4c21c 100644 (file)
@@ -97,7 +97,7 @@ subsys_initcall(db88f6281_pci_init);
 
 MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
        /* Maintainer: Saeed Bishara <saeed@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = db88f6281_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index f14dfb8..e4d199b 100644 (file)
@@ -102,7 +102,7 @@ static void __init dockstar_init(void)
 }
 
 MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = dockstar_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 41d1b40..6c40f78 100644 (file)
@@ -121,7 +121,7 @@ static void __init guruplug_init(void)
 
 MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
        /* Maintainer: Siddarth Gore <gores@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = guruplug_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 00cca22..9a1e917 100644 (file)
@@ -163,7 +163,7 @@ subsys_initcall(mv88f6281gtw_ge_pci_init);
 
 MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = mv88f6281gtw_ge_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 7cdab57..8849bcc 100644 (file)
@@ -258,7 +258,7 @@ static void __init netspace_v2_init(void)
 
 #ifdef CONFIG_MACH_NETSPACE_V2
 MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = netspace_v2_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
@@ -269,7 +269,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_INETSPACE_V2
 MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = netspace_v2_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
@@ -280,7 +280,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_NETSPACE_MAX_V2
 MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = netspace_v2_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 6be627d..1ba12c4 100644 (file)
@@ -399,7 +399,7 @@ static void __init netxbig_v2_init(void)
 
 #ifdef CONFIG_MACH_NET2BIG_V2
 MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = netxbig_v2_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
@@ -410,7 +410,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_NET5BIG_V2
 MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = netxbig_v2_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index f69beef..5660ca6 100644 (file)
@@ -214,7 +214,7 @@ subsys_initcall(openrd_pci_init);
 #ifdef CONFIG_MACH_OPENRD_BASE
 MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
        /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = openrd_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
@@ -226,7 +226,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_OPENRD_CLIENT
 MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
        /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = openrd_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
@@ -238,7 +238,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_OPENRD_ULTIMATE
 MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
        /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = openrd_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 75c6601..6663869 100644 (file)
@@ -79,7 +79,7 @@ subsys_initcall(rd88f6192_pci_init);
 
 MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
        /* Maintainer: Saeed Bishara <saeed@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = rd88f6192_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 0f75494..66b3c05 100644 (file)
@@ -115,7 +115,7 @@ subsys_initcall(rd88f6281_pci_init);
 
 MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
        /* Maintainer: Saeed Bishara <saeed@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = rd88f6281_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 17de0bf..8b102d6 100644 (file)
@@ -138,7 +138,7 @@ static void __init sheevaplug_init(void)
 #ifdef CONFIG_MACH_SHEEVAPLUG
 MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
        /* Maintainer: shadi Ammouri <shadi@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = sheevaplug_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
@@ -149,7 +149,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
 MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = sheevaplug_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index e6b9b1b..ea104fb 100644 (file)
@@ -201,7 +201,7 @@ subsys_initcall(hp_t5325_pci_init);
 
 MACHINE_START(T5325, "HP t5325 Thin Client")
        /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = hp_t5325_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 68f32f2..262c034 100644 (file)
@@ -132,7 +132,7 @@ subsys_initcall(ts219_pci_init);
 
 MACHINE_START(TS219, "QNAP TS-119/TS-219")
        /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = qnap_ts219_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index d5d0099..b68f5b4 100644 (file)
@@ -176,7 +176,7 @@ subsys_initcall(ts41x_pci_init);
 
 MACHINE_START(TS41X, "QNAP TS-41x")
        /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = qnap_ts41x_init,
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
index 3ca4f8e..a5fcc7c 100644 (file)
@@ -223,7 +223,7 @@ static void __init acs5k_init(void)
 
 MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
        /* Maintainer: Simtec Electronics. */
-       .boot_params    = KS8695_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = acs5k_init,
index 1338cb3..fb91a71 100644 (file)
@@ -121,7 +121,7 @@ static void __init dsm320_init(void)
 
 MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
        /* Maintainer: Simtec Electronics. */
-       .boot_params    = KS8695_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = dsm320_init,
index e2e3cba..8f67a75 100644 (file)
@@ -53,7 +53,7 @@ static void __init micrel_init(void)
 
 MACHINE_START(KS8695, "KS8695 Centaur Development Board")
        /* Maintainer: Micrel Semiconductor Inc. */
-       .boot_params    = KS8695_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = micrel_init,
index 7993b09..9b621e1 100644 (file)
@@ -382,7 +382,7 @@ arch_initcall(lpc32xx_display_uid);
 
 MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
        /* Maintainer: Kevin Wells, NXP Semiconductors */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .map_io         = lpc32xx_map_io,
        .init_irq       = lpc32xx_init_irq,
        .timer          = &lpc32xx_timer,
index 18a3c97..16c86f8 100644 (file)
@@ -93,7 +93,7 @@ static void __init halibut_map_io(void)
 }
 
 MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .fixup          = halibut_fixup,
        .map_io         = halibut_map_io,
        .init_irq       = halibut_init_irq,
index 7a9a03e..8a1672e 100644 (file)
@@ -74,7 +74,7 @@ static void __init mahimahi_map_io(void)
 extern struct sys_timer msm_timer;
 
 MACHINE_START(MAHIMAHI, "mahimahi")
-       .boot_params    = 0x20000100,
+       .atag_offset    = 0x100,
        .fixup          = mahimahi_fixup,
        .map_io         = mahimahi_map_io,
        .init_irq       = msm_init_irq,
index c03f269..a807655 100644 (file)
@@ -130,7 +130,7 @@ static void __init msm7x2x_map_io(void)
 }
 
 MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
-       .boot_params    = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = msm7x2x_map_io,
        .init_irq       = msm7x2x_init_irq,
        .init_machine   = msm7x2x_init,
@@ -138,7 +138,7 @@ MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
 MACHINE_END
 
 MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
-       .boot_params    = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = msm7x2x_map_io,
        .init_irq       = msm7x2x_init_irq,
        .init_machine   = msm7x2x_init,
@@ -146,7 +146,7 @@ MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
 MACHINE_END
 
 MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
-       .boot_params    = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = msm7x2x_map_io,
        .init_irq       = msm7x2x_init_irq,
        .init_machine   = msm7x2x_init,
@@ -154,7 +154,7 @@ MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
 MACHINE_END
 
 MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
-       .boot_params    = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = msm7x2x_map_io,
        .init_irq       = msm7x2x_init_irq,
        .init_machine   = msm7x2x_init,
index b7a8496..5a2ab68 100644 (file)
@@ -106,7 +106,7 @@ static void __init msm7x30_map_io(void)
 }
 
 MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
-       .boot_params = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = msm7x30_map_io,
        .init_irq = msm7x30_init_irq,
        .init_machine = msm7x30_init,
@@ -114,7 +114,7 @@ MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
-       .boot_params = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = msm7x30_map_io,
        .init_irq = msm7x30_init_irq,
        .init_machine = msm7x30_init,
@@ -122,7 +122,7 @@ MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
-       .boot_params = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = msm7x30_map_io,
        .init_irq = msm7x30_init_irq,
        .init_machine = msm7x30_init,
index 6a96911..51109b1 100644 (file)
@@ -193,7 +193,7 @@ static void __init qsd8x50_init(void)
 }
 
 MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
-       .boot_params = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = qsd8x50_map_io,
        .init_irq = qsd8x50_init_irq,
        .init_machine = qsd8x50_init,
@@ -201,7 +201,7 @@ MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
 MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
-       .boot_params = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = qsd8x50_map_io,
        .init_irq = qsd8x50_init_irq,
        .init_machine = qsd8x50_init,
index 68f930f..dc0bcb5 100644 (file)
@@ -105,7 +105,7 @@ static void __init sapphire_map_io(void)
 
 MACHINE_START(SAPPHIRE, "sapphire")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-       .boot_params    = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset    = 0x100,
        .fixup          = sapphire_fixup,
        .map_io         = sapphire_map_io,
        .init_irq       = sapphire_init_irq,
index 8143867..22d5694 100644 (file)
@@ -93,7 +93,7 @@ static void __init trout_map_io(void)
 }
 
 MACHINE_START(TROUT, "HTC Dream")
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .fixup          = trout_fixup,
        .map_io         = trout_map_io,
        .init_irq       = trout_init_irq,
index 20f3f12..0e94268 100644 (file)
@@ -145,7 +145,7 @@ subsys_initcall(wxl_pci_init);
 
 MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
        /* Maintainer: Sebastien Requiem <sebastien@requiem.fr> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = wxl_init,
        .map_io         = mv78xx0_map_io,
        .init_early     = mv78xx0_init_early,
index df5aebe..50b85ae 100644 (file)
@@ -93,7 +93,7 @@ subsys_initcall(db78x00_pci_init);
 
 MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = db78x00_init,
        .map_io         = mv78xx0_map_io,
        .init_early     = mv78xx0_init_early,
index d927f14..e85222e 100644 (file)
@@ -78,7 +78,7 @@ subsys_initcall(rd78x00_pci_init);
 
 MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = rd78x00_masa_init,
        .map_io         = mv78xx0_map_io,
        .init_early     = mv78xx0_init_early,
index 68934ea..e01af94 100644 (file)
@@ -293,7 +293,7 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
        /* Maintainer: Eric Bénard <eric@eukrea.com> */
-       .boot_params = MX51_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx51_map_io,
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
index ff096d5..b41fc27 100644 (file)
@@ -331,7 +331,7 @@ static struct sys_timer mxc_timer = {
 
 MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
        /* Maintainer: Eric Bénard <eric@eukrea.com> */
-       .boot_params = MX51_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx51_map_io,
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
index 07a3815..a50174e 100644 (file)
@@ -169,7 +169,7 @@ static struct sys_timer mx51_3ds_timer = {
 
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
        /* Maintainer: Freescale Semiconductor, Inc. */
-       .boot_params = MX51_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx51_map_io,
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
index 11b0ff6..468926a 100644 (file)
@@ -416,7 +416,7 @@ static struct sys_timer mx51_babbage_timer = {
 
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
        /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
-       .boot_params = MX51_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx51_map_io,
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
index 551daf8..c36880d 100644 (file)
@@ -280,7 +280,7 @@ static struct sys_timer mx51_efikamx_timer = {
 
 MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
        /* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
-       .boot_params = MX51_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx51_map_io,
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
index 8a9bca2..ba5436a 100644 (file)
@@ -266,7 +266,7 @@ static struct sys_timer mx51_efikasb_timer = {
 };
 
 MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
-       .boot_params = MX51_PHYS_OFFSET + 0x100,
+       .atag_offset = 0x100,
        .map_io = mx51_map_io,
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
index ca8b203..90903dd 100644 (file)
@@ -200,7 +200,7 @@ static void __init nxdb500_init(void)
 }
 
 MACHINE_START(NXDB500, "Hilscher nxdb500")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
        .timer          = &netx_timer,
index d775cbe..c63384a 100644 (file)
@@ -93,7 +93,7 @@ static void __init nxdkn_init(void)
 }
 
 MACHINE_START(NXDKN, "Hilscher nxdkn")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
        .timer          = &netx_timer,
index de369cd..8f548ec 100644 (file)
@@ -177,7 +177,7 @@ static void __init nxeb500hmi_init(void)
 }
 
 MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
        .timer          = &netx_timer,
index 1399303..398a75f 100644 (file)
@@ -276,7 +276,7 @@ static void __init nhk8815_platform_init(void)
 
 MACHINE_START(NOMADIK, "NHK8815")
        /* Maintainer: ST MicroElectronics */
-       .boot_params    = 0x100,
+       .atag_offset    = 0x100,
        .map_io         = cpu8815_map_io,
        .init_irq       = cpu8815_init_irq,
        .timer          = &nomadik_timer,
index d702570..1f741b1 100644 (file)
@@ -35,7 +35,6 @@ static void __init nuc932evb_init(void)
 
 MACHINE_START(NUC932EVB, "NUC932EVB")
        /* Maintainer: Wan ZongShun */
-       .boot_params    = 0,
        .map_io         = nuc932evb_map_io,
        .init_irq       = nuc93x_init_irq,
        .init_machine   = nuc932evb_init,
index 312ea6b..eb36b25 100644 (file)
@@ -386,7 +386,7 @@ static void __init ams_delta_map_io(void)
 
 MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
        /* Maintainer: Jonathan McDowell <noodles@earth.li> */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = ams_delta_map_io,
        .reserve        = omap_reserve,
        .init_irq       = ams_delta_init_irq,
index a6b1bea..999789c 100644 (file)
@@ -389,7 +389,7 @@ static void __init omap_fsample_map_io(void)
 
 MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = omap_fsample_map_io,
        .reserve        = omap_reserve,
        .init_irq       = omap_fsample_init_irq,
index 04fc356..23cc9e4 100644 (file)
@@ -94,7 +94,7 @@ static void __init omap_generic_map_io(void)
 
 MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
        /* Maintainer: Tony Lindgren <tony@atomide.com> */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = omap_generic_map_io,
        .reserve        = omap_reserve,
        .init_irq       = omap_generic_init_irq,
index cb7fb1a..6c70c28 100644 (file)
@@ -461,7 +461,7 @@ static void __init h2_map_io(void)
 
 MACHINE_START(OMAP_H2, "TI-H2")
        /* Maintainer: Imre Deak <imre.deak@nokia.com> */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = h2_map_io,
        .reserve        = omap_reserve,
        .init_irq       = h2_init_irq,
index 31f3487..8e2b64a 100644 (file)
@@ -449,7 +449,7 @@ static void __init h3_map_io(void)
 
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
        /* Maintainer: Texas Instruments, Inc. */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = h3_map_io,
        .reserve        = omap_reserve,
        .init_irq       = h3_init_irq,
index 36e06ea..e81ead1 100644 (file)
@@ -611,7 +611,7 @@ static void __init htcherald_init_irq(void)
 MACHINE_START(HERALD, "HTC Herald")
        /* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
        /* Maintainer: wing-linux.sourceforge.net */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = htcherald_map_io,
        .reserve        = omap_reserve,
        .init_irq       = htcherald_init_irq,
index 0b1ba46..8b03459 100644 (file)
@@ -459,7 +459,7 @@ static void __init innovator_map_io(void)
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
        /* Maintainer: MontaVista Software, Inc. */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = innovator_map_io,
        .reserve        = omap_reserve,
        .init_irq       = innovator_init_irq,
index 5469ce2..6825635 100644 (file)
@@ -264,7 +264,7 @@ static void __init omap_nokia770_map_io(void)
 }
 
 MACHINE_START(NOKIA770, "Nokia 770")
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = omap_nokia770_map_io,
        .reserve        = omap_reserve,
        .init_irq       = omap_nokia770_init_irq,
index b08a213..44b8e93 100644 (file)
@@ -583,7 +583,7 @@ static void __init osk_map_io(void)
 
 MACHINE_START(OMAP_OSK, "TI-OSK")
        /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = osk_map_io,
        .reserve        = omap_reserve,
        .init_irq       = osk_init_irq,
index 459cb6b..3d8cd90 100644 (file)
@@ -275,7 +275,7 @@ static void __init omap_palmte_map_io(void)
 }
 
 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = omap_palmte_map_io,
        .reserve        = omap_reserve,
        .init_irq       = omap_palmte_init_irq,
index b214f45..d0eefe8 100644 (file)
@@ -321,7 +321,7 @@ static void __init omap_palmtt_map_io(void)
 }
 
 MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = omap_palmtt_map_io,
        .reserve        = omap_reserve,
        .init_irq       = omap_palmtt_init_irq,
index 9b0ea48..98e79bc 100644 (file)
@@ -341,7 +341,7 @@ omap_palmz71_map_io(void)
 }
 
 MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = omap_palmz71_map_io,
        .reserve        = omap_reserve,
        .init_irq       = omap_palmz71_init_irq,
index 67acd41..ad3a156 100644 (file)
@@ -350,7 +350,7 @@ static void __init omap_perseus2_map_io(void)
 
 MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
        /* Maintainer: Kevin Hilman <kjh@hilman.org> */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = omap_perseus2_map_io,
        .reserve        = omap_reserve,
        .init_irq       = omap_perseus2_init_irq,
index 9c3b7c5..602b55c 100644 (file)
@@ -421,7 +421,7 @@ static void __init omap_sx1_map_io(void)
 }
 
 MACHINE_START(SX1, "OMAP310 based Siemens SX1")
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = omap_sx1_map_io,
        .reserve        = omap_reserve,
        .init_irq       = omap_sx1_init_irq,
index 036edc0..8016515 100644 (file)
@@ -301,7 +301,7 @@ static void __init voiceblue_init(void)
 
 MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
        /* Maintainer: Ladislav Michl <michl@2n.cz> */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .map_io         = voiceblue_map_io,
        .reserve        = omap_reserve,
        .init_irq       = voiceblue_init_irq,
index 870886a..1cfa1b6 100644 (file)
@@ -121,6 +121,7 @@ void __init omap1_map_common_io(void)
 #endif
 
        omap_sram_init();
+       omap_init_consistent_dma_size();
 }
 
 /*
index 2028464..195157d 100644 (file)
@@ -256,7 +256,7 @@ static void __init omap_2430sdp_map_io(void)
 
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
        /* Maintainer: Syed Khasim - Texas Instruments Inc */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap_2430sdp_map_io,
        .init_early     = omap_2430sdp_init_early,
index bd600cf..2430531 100644 (file)
@@ -729,7 +729,7 @@ static void __init omap_3430sdp_init(void)
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
        /* Maintainer: Syed Khasim - Texas Instruments Inc */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap_3430sdp_init_early,
index e4f37b5..8b5b5aa 100644 (file)
@@ -215,7 +215,7 @@ static void __init omap_sdp_init(void)
 }
 
 MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap_sdp_init_early,
index c7cef44..be93110 100644 (file)
@@ -838,7 +838,7 @@ static void __init omap_4430sdp_map_io(void)
 
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
        /* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap_4430sdp_map_io,
        .init_early     = omap_4430sdp_init_early,
index 933e935..db110fd 100644 (file)
@@ -98,7 +98,7 @@ static void __init am3517_crane_init(void)
 }
 
 MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = am3517_crane_init_early,
index f3006c3..1325085 100644 (file)
@@ -490,7 +490,7 @@ static void __init am3517_evm_init(void)
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = am3517_evm_init_early,
index 7021170..67800e6 100644 (file)
@@ -350,7 +350,7 @@ static void __init omap_apollon_map_io(void)
 
 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
        /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap_apollon_map_io,
        .init_early     = omap_apollon_init_early,
index 3af8aab..38179c1 100644 (file)
@@ -634,7 +634,7 @@ static void __init cm_t3730_init(void)
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = cm_t35_init_early,
@@ -644,7 +644,7 @@ MACHINE_START(CM_T35, "Compulab CM-T35")
 MACHINE_END
 
 MACHINE_START(CM_T3730, "Compulab CM-T3730")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = cm_t35_init_early,
index 05c72f4..aed9c29 100644 (file)
@@ -299,7 +299,7 @@ static void __init cm_t3517_init(void)
 }
 
 MACHINE_START(CM_T3517, "Compulab CM-T3517")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = cm_t3517_init_early,
index b6002ec..99a4243 100644 (file)
@@ -667,7 +667,7 @@ static void __init devkit8000_init(void)
 }
 
 MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = devkit8000_init_early,
index 54db41a..2564269 100644 (file)
@@ -66,7 +66,7 @@ static void __init omap_generic_map_io(void)
 /* XXX This machine entry name should be updated */
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
        /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap_generic_map_io,
        .init_early     = omap_generic_init_early,
index 45de2b3..a58c6ba 100644 (file)
@@ -382,7 +382,7 @@ static void __init omap_h4_map_io(void)
 
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
        /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap_h4_map_io,
        .init_early     = omap_h4_init_early,
index 35be778..7040352 100644 (file)
@@ -672,7 +672,7 @@ static void __init igep_init(void)
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = igep_init_early,
@@ -682,7 +682,7 @@ MACHINE_START(IGEP0020, "IGEP v2 board")
 MACHINE_END
 
 MACHINE_START(IGEP0030, "IGEP OMAP3 module")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = igep_init_early,
index 218764c..edf752b 100644 (file)
@@ -333,7 +333,7 @@ static void __init omap_ldp_init(void)
 }
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap_ldp_init_early,
index e11f0c5..6ce7481 100644 (file)
@@ -695,7 +695,7 @@ static void __init n8x0_init_machine(void)
 }
 
 MACHINE_START(NOKIA_N800, "Nokia N800")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = n8x0_map_io,
        .init_early     = n8x0_init_early,
@@ -705,7 +705,7 @@ MACHINE_START(NOKIA_N800, "Nokia N800")
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = n8x0_map_io,
        .init_early     = n8x0_init_early,
@@ -715,7 +715,7 @@ MACHINE_START(NOKIA_N810, "Nokia N810")
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = n8x0_map_io,
        .init_early     = n8x0_init_early,
index 3ae16b4..1fde8a0 100644 (file)
@@ -557,7 +557,7 @@ static void __init omap3_beagle_init(void)
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
        /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap3_beagle_init_early,
index c452b3f..15c69a0 100644 (file)
@@ -681,7 +681,7 @@ static void __init omap3_evm_init(void)
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
        /* Maintainer: Syed Mohammed Khasim - Texas Instruments */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap3_evm_init_early,
index 703aeb5..01354a2 100644 (file)
@@ -209,7 +209,7 @@ static void __init omap3logic_init(void)
 }
 
 MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .map_io         = omap3_map_io,
        .init_early     = omap3logic_init_early,
        .init_irq       = omap3_init_irq,
@@ -218,7 +218,7 @@ MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
 MACHINE_END
 
 MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .map_io         = omap3_map_io,
        .init_early     = omap3logic_init_early,
        .init_irq       = omap3_init_irq,
index 080d7bd..ace5693 100644 (file)
@@ -606,7 +606,7 @@ static void __init omap3pandora_init(void)
 }
 
 MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap3pandora_init_early,
index 8e10498..ba13e1d 100644 (file)
@@ -494,7 +494,7 @@ static void __init omap3_stalker_init(void)
 
 MACHINE_START(SBC3530, "OMAP3 STALKER")
        /* Maintainer: Jason Lam -lzg@ema-tech.com */
-       .boot_params            = 0x80000100,
+       .atag_offset            = 0x100,
        .map_io                 = omap3_map_io,
        .init_early             = omap3_stalker_init_early,
        .init_irq               = omap3_stalker_init_irq,
index 852ea04..49e4bd2 100644 (file)
@@ -404,7 +404,7 @@ static void __init omap3_touchbook_init(void)
 
 MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
        /* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap3_touchbook_init_early,
index 9aaa960..683bede 100644 (file)
@@ -583,7 +583,7 @@ static void __init omap4_panda_map_io(void)
 
 MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
        /* Maintainer: David Anders - Texas Instruments Inc */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap4_panda_map_io,
        .init_early     = omap4_panda_init_early,
index f949a99..e592fb1 100644 (file)
@@ -561,7 +561,7 @@ static void __init overo_init(void)
 }
 
 MACHINE_START(OVERO, "Gumstix Overo")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = overo_init_early,
index 7dfed24..9a8ce23 100644 (file)
@@ -153,7 +153,7 @@ static void __init rm680_map_io(void)
 }
 
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = rm680_map_io,
        .init_early     = rm680_init_early,
index 5ea142f..a6c473b 100644 (file)
@@ -156,7 +156,7 @@ static void __init rx51_reserve(void)
 
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
        /* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = rx51_reserve,
        .map_io         = rx51_map_io,
        .init_early     = rx51_init_early,
index a85d5b0..e41958a 100644 (file)
@@ -48,7 +48,7 @@ static void __init ti8168_evm_map_io(void)
 
 MACHINE_START(TI8168EVM, "ti8168evm")
        /* Maintainer: Texas Instruments */
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .map_io         = ti8168_evm_map_io,
        .init_early     = ti8168_init_early,
        .init_irq       = ti816x_init_irq,
index 8a98c3c..72f1db4 100644 (file)
@@ -133,7 +133,7 @@ static void __init omap_zoom_init(void)
 }
 
 MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap_zoom_init_early,
@@ -143,7 +143,7 @@ MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
 MACHINE_END
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
-       .boot_params    = 0x80000100,
+       .atag_offset    = 0x100,
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap_zoom_init_early,
index ffd55b1..b9b8446 100644 (file)
@@ -3078,6 +3078,7 @@ static struct clk gpt12_fck = {
        .name           = "gpt12_fck",
        .ops            = &clkops_null,
        .parent         = &secure_32k_fck,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -3085,6 +3086,7 @@ static struct clk wdt1_fck = {
        .name           = "wdt1_fck",
        .ops            = &clkops_null,
        .parent         = &secure_32k_fck,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
index 2af0e3f..c0b6fbd 100644 (file)
@@ -3376,10 +3376,18 @@ int __init omap4xxx_clk_init(void)
        } else if (cpu_is_omap446x()) {
                cpu_mask = RATE_IN_4460;
                cpu_clkflg = CK_446X;
+       } else {
+               return 0;
        }
 
        clk_init(&omap2_clk_functions);
-       omap2_clk_disable_clkdm_control();
+
+       /*
+        * Must stay commented until all OMAP SoC drivers are
+        * converted to runtime PM, or drivers may start crashing
+        *
+        * omap2_clk_disable_clkdm_control();
+        */
 
        for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
                                                                          c++)
index ab7db08..8f08906 100644 (file)
@@ -747,6 +747,7 @@ int clkdm_wakeup(struct clockdomain *clkdm)
        spin_lock_irqsave(&clkdm->lock, flags);
        clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
        ret = arch_clkdm->clkdm_wakeup(clkdm);
+       ret |= pwrdm_state_switch(clkdm->pwrdm.ptr);
        spin_unlock_irqrestore(&clkdm->lock, flags);
        return ret;
 }
@@ -818,6 +819,7 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
        spin_lock_irqsave(&clkdm->lock, flags);
        clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
        arch_clkdm->clkdm_deny_idle(clkdm);
+       pwrdm_state_switch(clkdm->pwrdm.ptr);
        spin_unlock_irqrestore(&clkdm->lock, flags);
 }
 
index 2ce1ce6..d6d01cb 100644 (file)
@@ -16,7 +16,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -250,6 +249,7 @@ static void __init _omap2_map_common_io(void)
 
        omap2_check_revision();
        omap_sram_init();
+       omap_init_consistent_dma_size();
 }
 
 #ifdef CONFIG_SOC_OMAP2420
index 16743c7..408193d 100644 (file)
@@ -192,6 +192,7 @@ static struct omap_hwmod_addr_space omap2430_usbhsotg_addrs[] = {
                .pa_end         = OMAP243X_HS_BASE + SZ_4K - 1,
                .flags          = ADDR_TYPE_RT
        },
+       { }
 };
 
 /*  l4_core ->usbhsotg  interface */
index 3feb359..472bf22 100644 (file)
@@ -130,7 +130,6 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
                } else {
                        hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
                        clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-                       pwrdm_wait_transition(pwrdm);
                        sleep_switch = FORCEWAKEUP_SWITCH;
                }
        }
@@ -156,7 +155,6 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
                return ret;
        }
 
-       pwrdm_wait_transition(pwrdm);
        pwrdm_state_switch(pwrdm);
 err:
        return ret;
index 9af0847..ef71fdd 100644 (file)
@@ -195,28 +195,35 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
 
 /**
  * pwrdm_init - set up the powerdomain layer
- * @pwrdm_list: array of struct powerdomain pointers to register
+ * @pwrdms: array of struct powerdomain pointers to register
  * @custom_funcs: func pointers for arch specific implementations
  *
- * Loop through the array of powerdomains @pwrdm_list, registering all
- * that are available on the current CPU. If pwrdm_list is supplied
- * and not null, all of the referenced powerdomains will be
- * registered.  No return value.  XXX pwrdm_list is not really a
- * "list"; it is an array.  Rename appropriately.
+ * Loop through the array of powerdomains @pwrdms, registering all
+ * that are available on the current CPU.  Also, program all
+ * powerdomain target state as ON; this is to prevent domains from
+ * hitting low power states (if bootloader has target states set to
+ * something other than ON) and potentially even losing context while
+ * PM is not fully initialized.  The PM late init code can then program
+ * the desired target state for all the power domains.  No return
+ * value.
  */
-void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs)
+void pwrdm_init(struct powerdomain **pwrdms, struct pwrdm_ops *custom_funcs)
 {
        struct powerdomain **p = NULL;
+       struct powerdomain *temp_p;
 
        if (!custom_funcs)
                WARN(1, "powerdomain: No custom pwrdm functions registered\n");
        else
                arch_pwrdm = custom_funcs;
 
-       if (pwrdm_list) {
-               for (p = pwrdm_list; *p; p++)
+       if (pwrdms) {
+               for (p = pwrdms; *p; p++)
                        _pwrdm_register(*p);
        }
+
+       list_for_each_entry(temp_p, &pwrdm_list, node)
+               pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
 }
 
 /**
index 19cf5bf..8c83009 100644 (file)
@@ -336,7 +336,7 @@ static void __init d2net_init(void)
 
 #ifdef CONFIG_MACH_D2NET
 MACHINE_START(D2NET, "LaCie d2 Network")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = d2net_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
@@ -348,7 +348,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_BIGDISK
 MACHINE_START(BIGDISK, "LaCie Big Disk Network")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = d2net_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index a3e3e9e..88432ab 100644 (file)
@@ -359,7 +359,7 @@ static void __init db88f5281_init(void)
 
 MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
        /* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = db88f5281_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index a6eddae..9e5c166 100644 (file)
@@ -77,7 +77,7 @@ static int __init dns323_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        /*
         * Check for devices with hard-wired IRQs.
         */
-       irq = orion5x_pci_map_irq(const dev, slot, pin);
+       irq = orion5x_pci_map_irq(dev, slot, pin);
        if (irq != -1)
                return irq;
 
@@ -730,7 +730,7 @@ static void __init dns323_init(void)
 /* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
 MACHINE_START(DNS323, "D-Link DNS-323")
        /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = dns323_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index b67cff0..70a4e92 100644 (file)
@@ -251,7 +251,7 @@ static void __init edmini_v2_init(void)
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")
        /* Maintainer: Christopher Moore <moore@free.fr> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = edmini_v2_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 0038124..9115511 100644 (file)
@@ -380,7 +380,7 @@ static void __init kurobox_pro_init(void)
 #ifdef CONFIG_MACH_KUROBOX_PRO
 MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
        /* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = kurobox_pro_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
@@ -393,7 +393,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_LINKSTATION_PRO
 MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
        /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = kurobox_pro_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 5065803..9503fff 100644 (file)
@@ -318,7 +318,7 @@ static void __init lschl_init(void)
 
 MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
        /* Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = lschl_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 8503d0a..ed6d772 100644 (file)
@@ -265,7 +265,7 @@ static void __init ls_hgl_init(void)
 
 MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
        /* Maintainer: Zhu Qingsen <zhuqs@cn.fujistu.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = ls_hgl_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 9c82723..743f7f1 100644 (file)
@@ -267,7 +267,7 @@ static void __init lsmini_init(void)
 #ifdef CONFIG_MACH_LINKSTATION_MINI
 MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
        /* Maintainer: Alexey Kopytko <alexey@kopytko.ru> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = lsmini_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index ef3bb8e..6020e26 100644 (file)
@@ -261,7 +261,7 @@ static void __init mss2_init(void)
 
 MACHINE_START(MSS2, "Maxtor Shared Storage II")
        /* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = mss2_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 63ff10c..b3356ad 100644 (file)
@@ -229,7 +229,7 @@ static void __init mv2120_init(void)
 /* Warning: HP uses a wrong mach-type (=526) in their bootloader */
 MACHINE_START(MV2120, "HP Media Vault mv2120")
        /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = mv2120_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index e43b39c..6197c79 100644 (file)
@@ -419,7 +419,7 @@ static void __init net2big_init(void)
 
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(NET2BIG, "LaCie 2Big Network")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = net2big_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 28b8760..bc4a920 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/mbus.h>
+#include <video/vga.h>
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <plat/pcie.h>
index 291d22b..8c87666 100644 (file)
@@ -169,7 +169,7 @@ subsys_initcall(rd88f5181l_fxo_pci_init);
 
 MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
        /* Maintainer: Nicolas Pitre <nico@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = rd88f5181l_fxo_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 3f02362..994644f 100644 (file)
@@ -181,7 +181,7 @@ subsys_initcall(rd88f5181l_ge_pci_init);
 
 MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = rd88f5181l_ge_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 27fd38e..1903d25 100644 (file)
@@ -306,7 +306,7 @@ static void __init rd88f5182_init(void)
 
 MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
        /* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = rd88f5182_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index ad2eba9..e06fdae 100644 (file)
@@ -122,7 +122,7 @@ subsys_initcall(rd88f6183ap_ge_pci_init);
 
 MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = rd88f6183ap_ge_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index a34e4fa..3061832 100644 (file)
@@ -358,7 +358,7 @@ static void __init tsp2_init(void)
 
 MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
        /* Maintainer:  Sylver Bruneau <sylver.bruneau@googlemail.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = tsp2_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index c983161..3dbcd5e 100644 (file)
@@ -323,7 +323,7 @@ static void __init qnap_ts209_init(void)
 
 MACHINE_START(TS209, "QNAP TS-109/TS-209")
        /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = qnap_ts209_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index cc33b22..23c9e2e 100644 (file)
@@ -312,7 +312,7 @@ static void __init qnap_ts409_init(void)
 
 MACHINE_START(TS409, "QNAP TS-409")
        /* Maintainer:  Sylver Bruneau <sylver.bruneau@gmail.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = qnap_ts409_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 6b7b541..6c75cd3 100644 (file)
@@ -621,7 +621,7 @@ static void __init ts78xx_init(void)
 
 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
        /* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = ts78xx_init,
        .map_io         = ts78xx_map_io,
        .init_early     = orion5x_init_early,
index 2653595..1c63a76 100644 (file)
@@ -173,7 +173,7 @@ subsys_initcall(wnr854t_pci_init);
 
 MACHINE_START(WNR854T, "Netgear WNR854T")
        /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = wnr854t_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 251ef15..4fd9f18 100644 (file)
@@ -261,7 +261,7 @@ subsys_initcall(wrt350n_v2_pci_init);
 
 MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
        /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_machine   = wrt350n_v2_init,
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
index 6339975..cdb95e7 100644 (file)
@@ -264,7 +264,7 @@ extern struct sys_timer pnx4008_timer;
 
 MACHINE_START(PNX4008, "Philips PNX4008")
        /* Maintainer: MontaVista Software Inc. */
-       .boot_params            = 0x80000100,
+       .atag_offset            = 0x100,
        .map_io                 = pnx4008_map_io,
        .init_irq               = pnx4008_init_irq,
        .init_machine           = pnx4008_init,
index f9a2aaf..615a4e7 100644 (file)
@@ -481,6 +481,7 @@ static void __init sirfsoc_clk_init(void)
 
 static struct of_device_id clkc_ids[] = {
        { .compatible = "sirf,prima2-clkc" },
+       {},
 };
 
 void __init sirfsoc_of_clk_init(void)
index c3404cb..7af254d 100644 (file)
@@ -51,6 +51,7 @@ static __init void sirfsoc_irq_init(void)
 
 static struct of_device_id intc_ids[]  = {
        { .compatible = "sirf,prima2-intc" },
+       {},
 };
 
 void __init sirfsoc_of_irq_init(void)
index f57124b..5654a04 100644 (file)
@@ -31,7 +31,7 @@ static const char *prima2cb_dt_match[] __initdata = {
 
 MACHINE_START(PRIMA2_EVB, "prima2cb")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .init_early     = sirfsoc_of_clk_init,
        .map_io         = sirfsoc_map_lluart,
        .init_irq       = sirfsoc_of_irq_init,
index d074786..492cfa8 100644 (file)
@@ -19,6 +19,7 @@ static DEFINE_MUTEX(rstc_lock);
 
 static struct of_device_id rstc_ids[]  = {
        { .compatible = "sirf,prima2-rstc" },
+       {},
 };
 
 static int __init sirfsoc_of_rstc_init(void)
index 44027f3..ed7ec48 100644 (file)
@@ -190,6 +190,7 @@ static void __init sirfsoc_timer_init(void)
 
 static struct of_device_id timer_ids[] = {
        { .compatible = "sirf,prima2-tick" },
+       {},
 };
 
 static void __init sirfsoc_of_timer_map(void)
index ef3e8b1..7765d67 100644 (file)
@@ -828,5 +828,5 @@ MACHINE_START(BALLOON3, "Balloon3")
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = balloon3_init,
-       .boot_params    = PLAT_PHYS_OFFSET + 0x100,
+       .atag_offset    = 0x100,
 MACHINE_END
index 648b0ab..4efc16d 100644 (file)
@@ -148,7 +148,7 @@ static void __init capc7117_init(void)
 
 MACHINE_START(CAPC7117,
              "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
-       .boot_params = 0xa0000100,
+       .atag_offset = 0x100,
        .map_io = pxa3xx_map_io,
        .init_irq = pxa3xx_init_irq,
        .handle_irq = pxa3xx_handle_irq,
index 13cf518..349896c 100644 (file)
@@ -513,7 +513,7 @@ static void __init cmx2xx_map_io(void)
 #endif
 
 MACHINE_START(ARMCORE, "Compulab CM-X2XX")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = cmx2xx_map_io,
        .nr_irqs        = CMX2XX_NR_IRQS,
        .init_irq       = cmx2xx_init_irq,
index b6a5134..9ac0225 100644 (file)
@@ -852,7 +852,7 @@ static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
 }
 
 MACHINE_START(CM_X300, "CM-X300 module")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
index 8709209..7db6646 100644 (file)
@@ -306,7 +306,7 @@ static void __init colibri_pxa270_income_init(void)
 }
 
 MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
-       .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
+       .atag_offset    = 0x100,
        .init_machine   = colibri_pxa270_init,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
@@ -315,7 +315,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
 MACHINE_END
 
 MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .init_machine   = colibri_pxa270_income_init,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
index 60a6781..c825e8b 100644 (file)
@@ -183,7 +183,7 @@ void __init colibri_pxa300_init(void)
 }
 
 MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
-       .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
+       .atag_offset    = 0x100,
        .init_machine   = colibri_pxa300_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
index d2c6631..692e1ff 100644 (file)
@@ -253,7 +253,7 @@ void __init colibri_pxa320_init(void)
 }
 
 MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
-       .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
+       .atag_offset    = 0x100,
        .init_machine   = colibri_pxa320_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
index fe812ea..5e2cf39 100644 (file)
@@ -272,7 +272,7 @@ static void __init csb726_init(void)
 }
 
 MACHINE_START(CSB726, "Cogent CSB726")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
index 2e37ea5..94acc0b 100644 (file)
@@ -1299,7 +1299,7 @@ static void __init em_x270_init(void)
 }
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
@@ -1308,7 +1308,7 @@ MACHINE_START(EM_X270, "Compulab EM-X270")
 MACHINE_END
 
 MACHINE_START(EXEDA, "Compulab eXeda")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
index b4599ec..e823c54 100644 (file)
@@ -189,7 +189,7 @@ static void __init e330_init(void)
 
 MACHINE_START(E330, "Toshiba e330")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
@@ -239,7 +239,7 @@ static void __init e350_init(void)
 
 MACHINE_START(E350, "Toshiba e350")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
@@ -362,7 +362,7 @@ static void __init e400_init(void)
 
 MACHINE_START(E400, "Toshiba e400")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
@@ -551,7 +551,7 @@ static void __init e740_init(void)
 
 MACHINE_START(E740, "Toshiba e740")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
@@ -743,7 +743,7 @@ static void __init e750_init(void)
 
 MACHINE_START(E750, "Toshiba e750")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
@@ -948,7 +948,7 @@ static void __init e800_init(void)
 
 MACHINE_START(E800, "Toshiba e800")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
index b73eadb..8308eee 100644 (file)
@@ -797,7 +797,7 @@ static void __init a780_init(void)
 }
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
@@ -863,7 +863,7 @@ static void __init e680_init(void)
 }
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
@@ -929,7 +929,7 @@ static void __init a1200_init(void)
 }
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
@@ -1120,7 +1120,7 @@ static void __init a910_init(void)
 }
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
@@ -1186,7 +1186,7 @@ static void __init e6_init(void)
 }
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
@@ -1226,7 +1226,7 @@ static void __init e2_init(void)
 }
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
index deaa111..9c8208c 100644 (file)
@@ -233,7 +233,7 @@ static void __init gumstix_init(void)
 }
 
 MACHINE_START(GUMSTIX, "Gumstix")
-       .boot_params    = 0xa0000100, /* match u-boot bi_boot_params */
+       .atag_offset    = 0x100, /* match u-boot bi_boot_params */
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
index 0a23512..4b5e110 100644 (file)
@@ -203,7 +203,7 @@ static void __init h5000_init(void)
 }
 
 MACHINE_START(H5400, "HP iPAQ H5000")
-       .boot_params = 0xa0000100,
+       .atag_offset = 0x100,
        .map_io = pxa25x_map_io,
        .init_irq = pxa25x_init_irq,
        .handle_irq = pxa25x_handle_irq,
index a997d0a..f2c3245 100644 (file)
@@ -158,7 +158,7 @@ static void __init himalaya_init(void)
 
 
 MACHINE_START(HIMALAYA, "HTC Himalaya")
-       .boot_params = 0xa0000100,
+       .atag_offset = 0x100,
        .map_io = pxa25x_map_io,
        .init_irq = pxa25x_init_irq,
        .handle_irq = pxa25x_handle_irq,
index c748a47..6f6368e 100644 (file)
@@ -838,7 +838,7 @@ static void __init hx4700_init(void)
 }
 
 MACHINE_START(H4700, "HP iPAQ HX4700")
-       .boot_params  = 0xa0000100,
+       .atag_offset  = 0x100,
        .map_io       = pxa27x_map_io,
        .nr_irqs      = HX4700_NR_IRQS,
        .init_irq     = pxa27x_init_irq,
index d427429..f78d5db 100644 (file)
@@ -191,7 +191,7 @@ static void __init icontrol_init(void)
 }
 
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
index 8f97e15..0037e57 100644 (file)
@@ -437,7 +437,7 @@ static void __init littleton_init(void)
 }
 
 MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
        .nr_irqs        = LITTLETON_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
index c171d6e..16df0fc 100644 (file)
@@ -499,7 +499,7 @@ static void __init lpd270_map_io(void)
 
 MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
        /* Maintainer: Peter Barada */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = lpd270_map_io,
        .nr_irqs        = LPD270_NR_IRQS,
        .init_irq       = lpd270_init_irq,
index 5fe5bcd..4b796c3 100644 (file)
@@ -753,7 +753,7 @@ static void __init magician_init(void)
 
 
 MACHINE_START(MAGICIAN, "HTC Magician")
-       .boot_params = 0xa0000100,
+       .atag_offset = 0x100,
        .map_io = pxa27x_map_io,
        .nr_irqs = MAGICIAN_NR_IRQS,
        .init_irq = pxa27x_init_irq,
index 4622eb7..cc6e14f 100644 (file)
@@ -616,7 +616,7 @@ static void __init mainstone_map_io(void)
 
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
        /* Maintainer: MontaVista Software Inc. */
-       .boot_params    = 0xa0000100,   /* BLOB boot parameter setting */
+       .atag_offset    = 0x100,        /* BLOB boot parameter setting */
        .map_io         = mainstone_map_io,
        .nr_irqs        = MAINSTONE_NR_IRQS,
        .init_irq       = mainstone_init_irq,
index 64810f9..b938fc2 100644 (file)
@@ -751,7 +751,7 @@ static void mioa701_machine_exit(void)
 }
 
 MACHINE_START(MIOA701, "MIO A701")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = &pxa27x_map_io,
        .init_irq       = &pxa27x_init_irq,
        .handle_irq     = &pxa27x_handle_irq,
index fb40886..4af5d51 100644 (file)
@@ -92,7 +92,7 @@ static void __init mp900c_init(void)
 
 /* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
 MACHINE_START(NEC_MP900, "MobilePro900/C")
-       .boot_params    = 0xa0220100,
+       .atag_offset    = 0x220100,
        .timer          = &pxa_timer,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
index 6b77365..3d4a281 100644 (file)
@@ -342,7 +342,7 @@ static void __init palmld_init(void)
 }
 
 MACHINE_START(PALMLD, "Palm LifeDrive")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = palmld_map_io,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
index 9bd3e47..99d6bcf 100644 (file)
@@ -202,7 +202,7 @@ static void __init palmt5_init(void)
 }
 
 MACHINE_START(PALMT5, "Palm Tungsten|T5")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = palmt5_reserve,
        .init_irq       = pxa27x_init_irq,
index 6ad4a6c..6ec7cae 100644 (file)
@@ -537,7 +537,7 @@ static void __init palmtc_init(void)
 };
 
 MACHINE_START(PALMTC, "Palm Tungsten|C")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
index 664232f..9376da0 100644 (file)
@@ -356,7 +356,7 @@ static void __init palmte2_init(void)
 }
 
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
index bb27d4b..7346fbf 100644 (file)
@@ -440,7 +440,7 @@ static void __init centro_init(void)
 }
 
 MACHINE_START(TREO680, "Palm Treo 680")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
        .init_irq       = pxa27x_init_irq,
@@ -450,7 +450,7 @@ MACHINE_START(TREO680, "Palm Treo 680")
 MACHINE_END
 
 MACHINE_START(CENTRO, "Palm Centro 685")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
        .init_irq       = pxa27x_init_irq,
index fc42855..2b9e76f 100644 (file)
@@ -364,7 +364,7 @@ static void __init palmtx_init(void)
 }
 
 MACHINE_START(PALMTX, "Palm T|X")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = palmtx_map_io,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
index e61c1cc..68e18ba 100644 (file)
@@ -399,7 +399,7 @@ static void __init palmz72_init(void)
 }
 
 MACHINE_START(PALMZ72, "Palm Zire72")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
index ffa65df..0b825a3 100644 (file)
@@ -258,7 +258,7 @@ static void __init pcm027_map_io(void)
 
 MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
        /* Maintainer: Pengutronix */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pcm027_map_io,
        .nr_irqs        = PCM027_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
index bbcd905..6810cdd 100644 (file)
@@ -1086,7 +1086,7 @@ static void __init raumfeld_speaker_init(void)
 
 #ifdef CONFIG_MACH_RAUMFELD_RC
 MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
-       .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
+       .atag_offset    = 0x100,
        .init_machine   = raumfeld_controller_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
@@ -1097,7 +1097,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_RAUMFELD_CONNECTOR
 MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
-       .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
+       .atag_offset    = 0x100,
        .init_machine   = raumfeld_connector_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
@@ -1108,7 +1108,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_RAUMFELD_SPEAKER
 MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
-       .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
+       .atag_offset    = 0x100,
        .init_machine   = raumfeld_speaker_init,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
index df4356e..602d70b 100644 (file)
@@ -596,7 +596,7 @@ static void __init saar_init(void)
 
 MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq       = pxa3xx_handle_irq,
index ebd6379..5ce3403 100644 (file)
@@ -103,7 +103,7 @@ static void __init saarb_init(void)
 }
 
 MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
        .nr_irqs        = SAARB_NR_IRQS,
        .init_irq       = pxa95x_init_irq,
index 3f8d0af..4c9a48b 100644 (file)
@@ -1004,7 +1004,7 @@ MACHINE_START(INTELMOTE2, "IMOTE 2")
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
        .init_machine   = imote2_init,
-       .boot_params    = 0xA0000100,
+       .atag_offset    = 0x100,
 MACHINE_END
 #endif
 
@@ -1016,6 +1016,6 @@ MACHINE_START(STARGATE2, "Stargate 2")
        .handle_irq = pxa27x_handle_irq,
        .timer = &pxa_timer,
        .init_machine = stargate2_init,
-       .boot_params = 0xA0000100,
+       .atag_offset = 0x100,
 MACHINE_END
 #endif
index 32fb58e..ad47bb9 100644 (file)
@@ -489,7 +489,7 @@ static void __init tavorevb_init(void)
 
 MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq       = pxa3xx_handle_irq,
index fd5a8ea..fd56916 100644 (file)
@@ -125,7 +125,7 @@ static void __init evb3_init(void)
 }
 
 MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
        .nr_irqs        = TAVOREVB3_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
index c041750..35bbf13 100644 (file)
@@ -554,7 +554,7 @@ static void __init trizeps4_map_io(void)
 
 MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
        /* MAINTAINER("Jürgen Schindele") */
-       .boot_params    = TRIZEPS4_SDRAM_BASE + 0x100,
+       .atag_offset    = 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
        .init_irq       = pxa27x_init_irq,
@@ -564,7 +564,7 @@ MACHINE_END
 
 MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
        /* MAINTAINER("Jürgen Schindele") */
-       .boot_params    = TRIZEPS4_SDRAM_BASE + 0x100,
+       .atag_offset    = 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
        .init_irq       = pxa27x_init_irq,
index d4a3dc7..242ddae 100644 (file)
@@ -992,7 +992,7 @@ static void __init viper_map_io(void)
 
 MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
        /* Maintainer: Marc Zyngier <maz@misterjones.org> */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = viper_map_io,
        .init_irq       = viper_init_irq,
        .handle_irq     = pxa25x_handle_irq,
index 5f8490a..a7539a6 100644 (file)
@@ -716,7 +716,7 @@ static void __init vpac270_init(void)
 }
 
 MACHINE_START(VPAC270, "Voipac PXA270")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
index acc600f..54930cc 100644 (file)
@@ -180,7 +180,7 @@ static void __init xcep_init(void)
 }
 
 MACHINE_START(XCEP, "Iskratel XCEP")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .init_machine   = xcep_init,
        .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
index 6c9275a..65fed37 100644 (file)
@@ -718,7 +718,7 @@ static void __init z2_init(void)
 }
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
index 99c49bc..c424e7d 100644 (file)
@@ -904,7 +904,7 @@ static void __init zeus_map_io(void)
 
 MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
        /* Maintainer: Marc Zyngier <maz@misterjones.org> */
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = zeus_map_io,
        .nr_irqs        = ZEUS_NR_IRQS,
        .init_irq       = zeus_init_irq,
index 15ec66b..31d4968 100644 (file)
@@ -422,7 +422,7 @@ static void __init zylonite_init(void)
 }
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
-       .boot_params    = 0xa0000100,
+       .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
        .nr_irqs        = ZYLONITE_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
index 7a4e3b1..026c66a 100644 (file)
@@ -463,7 +463,7 @@ static void __init realview_eb_init(void)
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+       .atag_offset    = 0x100,
        .fixup          = realview_fixup,
        .map_io         = realview_eb_map_io,
        .init_early     = realview_init_early,
index ad5671a..7263dea 100644 (file)
@@ -358,7 +358,7 @@ static void __init realview_pb1176_init(void)
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+       .atag_offset    = 0x100,
        .fixup          = realview_pb1176_fixup,
        .map_io         = realview_pb1176_map_io,
        .init_early     = realview_init_early,
index b43644b..671ad6d 100644 (file)
@@ -360,7 +360,7 @@ static void __init realview_pb11mp_init(void)
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+       .atag_offset    = 0x100,
        .fixup          = realview_fixup,
        .map_io         = realview_pb11mp_map_io,
        .init_early     = realview_init_early,
index 763e8f3..cbf22df 100644 (file)
@@ -310,7 +310,7 @@ static void __init realview_pba8_init(void)
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+       .atag_offset    = 0x100,
        .fixup          = realview_fixup,
        .map_io         = realview_pba8_map_io,
        .init_early     = realview_init_early,
index 363b0ab..8ec7e52 100644 (file)
@@ -393,7 +393,7 @@ static void __init realview_pbx_init(void)
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+       .atag_offset    = 0x100,
        .fixup          = realview_pbx_fixup,
        .map_io         = realview_pbx_map_io,
        .init_early     = realview_init_early,
index 580b3c7..a9241eb 100644 (file)
@@ -218,7 +218,7 @@ extern struct sys_timer ioc_timer;
 
 MACHINE_START(RISCPC, "Acorn-RiscPC")
        /* Maintainer: Russell King */
-       .boot_params    = 0x10000100,
+       .atag_offset    = 0x100,
        .reserve_lp0    = 1,
        .reserve_lp1    = 1,
        .map_io         = rpc_map_io,
index dabc141..7983894 100644 (file)
@@ -236,7 +236,7 @@ static void __init amlm5900_init(void)
 }
 
 MACHINE_START(AML_M5900, "AML_M5900")
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = amlm5900_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = amlm5900_init,
index 1e2d536..a20ae1a 100644 (file)
@@ -657,7 +657,7 @@ static void __init bast_init(void)
 
 MACHINE_START(BAST, "Simtec-BAST")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = bast_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = bast_init,
index 2a2fa06..556c535 100644 (file)
@@ -744,7 +744,7 @@ static void __init h1940_init(void)
 
 MACHINE_START(H1940, "IPAQ-H1940")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = h1940_map_io,
        .reserve        = h1940_reserve,
        .init_irq       = h1940_init_irq,
index 079dcaa..1dc3e32 100644 (file)
@@ -586,7 +586,7 @@ MACHINE_START(N30, "Acer-N30")
        /* Maintainer: Christer Weinigel <christer@weinigel.se>,
                                Ben Dooks <ben-linux@fluff.org>
        */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .timer          = &s3c24xx_timer,
        .init_machine   = n30_init,
        .init_irq       = s3c24xx_init_irq,
@@ -596,7 +596,7 @@ MACHINE_END
 MACHINE_START(N35, "Acer-N35")
        /* Maintainer: Christer Weinigel <christer@weinigel.se>
        */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .timer          = &s3c24xx_timer,
        .init_machine   = n30_init,
        .init_irq       = s3c24xx_init_irq,
index 0aa16cd..f03f3fd 100644 (file)
@@ -116,7 +116,7 @@ static void __init otom11_init(void)
 
 MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
        /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = otom11_map_io,
        .init_machine   = otom11_init,
        .init_irq       = s3c24xx_init_irq,
index f44f775..367d376 100644 (file)
@@ -344,7 +344,7 @@ static void __init qt2410_machine_init(void)
 }
 
 MACHINE_START(QT2410, "QT2410")
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = qt2410_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = qt2410_machine_init,
index e17f033..99c9dfd 100644 (file)
@@ -111,7 +111,7 @@ static void __init smdk2410_init(void)
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
                                    * to SMDK2410 */
        /* Maintainer: Jonas Dietsche */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = smdk2410_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = smdk2410_init,
index 43c2b83..e0d0b6f 100644 (file)
@@ -146,7 +146,7 @@ static void __init tct_hammer_init(void)
 }
 
 MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = tct_hammer_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = tct_hammer_init,
index 6ccce5a..df47e8e 100644 (file)
@@ -400,7 +400,7 @@ static void __init vr1000_init(void)
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = vr1000_map_io,
        .init_machine   = vr1000_init,
        .init_irq       = s3c24xx_init_irq,
index 5eeb475..286ef17 100644 (file)
@@ -655,7 +655,7 @@ static void __init jive_machine_init(void)
 
 MACHINE_START(JIVE, "JIVE")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s3c24xx_init_irq,
        .map_io         = jive_map_io,
index 834cfb6..d6325ed 100644 (file)
@@ -128,7 +128,7 @@ static void __init smdk2413_machine_init(void)
 
 MACHINE_START(S3C2413, "S3C2413")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
 
        .fixup          = smdk2413_fixup,
        .init_irq       = s3c24xx_init_irq,
@@ -139,7 +139,7 @@ MACHINE_END
 
 MACHINE_START(SMDK2412, "SMDK2412")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
 
        .fixup          = smdk2413_fixup,
        .init_irq       = s3c24xx_init_irq,
@@ -150,7 +150,7 @@ MACHINE_END
 
 MACHINE_START(SMDK2413, "SMDK2413")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
 
        .fixup          = smdk2413_fixup,
        .init_irq       = s3c24xx_init_irq,
index 83544eb..5955c15 100644 (file)
@@ -156,7 +156,7 @@ static void __init vstms_init(void)
 }
 
 MACHINE_START(VSTMS, "VSTMS")
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
 
        .fixup          = vstms_fixup,
        .init_irq       = s3c24xx_init_irq,
index ac27ebb..a9eee53 100644 (file)
@@ -245,7 +245,7 @@ static void __init smdk2416_machine_init(void)
 
 MACHINE_START(SMDK2416, "SMDK2416")
        /* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2416_map_io,
index d708678..74f92fc 100644 (file)
@@ -498,7 +498,7 @@ static void __init anubis_init(void)
 
 MACHINE_START(ANUBIS, "Simtec-Anubis")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = anubis_map_io,
        .init_machine   = anubis_init,
        .init_irq       = s3c24xx_init_irq,
index 6c98b78..38887ee 100644 (file)
@@ -233,7 +233,7 @@ static void __init at2440evb_init(void)
 
 
 MACHINE_START(AT2440EVB, "AT2440EVB")
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = at2440evb_map_io,
        .init_machine   = at2440evb_init,
        .init_irq       = s3c24xx_init_irq,
index c10ddf4..de1e0ff 100644 (file)
@@ -595,7 +595,7 @@ static void __init gta02_machine_init(void)
 
 MACHINE_START(NEO1973_GTA02, "GTA02")
        /* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = gta02_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = gta02_machine_init,
index fc2dc0b..91fe0b4 100644 (file)
@@ -676,7 +676,7 @@ static void __init mini2440_init(void)
 
 MACHINE_START(MINI2440, "MINI2440")
        /* Maintainer: Michel Pollet <buserror@gmail.com> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = mini2440_map_io,
        .init_machine   = mini2440_init,
        .init_irq       = s3c24xx_init_irq,
index 37dd306..61c0bf1 100644 (file)
@@ -151,7 +151,7 @@ static void __init nexcoder_init(void)
 
 MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
        /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = nexcoder_map_io,
        .init_machine   = nexcoder_init,
        .init_irq       = s3c24xx_init_irq,
index d885363..dc142eb 100644 (file)
@@ -447,7 +447,7 @@ static void __init osiris_init(void)
 
 MACHINE_START(OSIRIS, "Simtec-OSIRIS")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = osiris_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = osiris_init,
index 27ea950..684dbb3 100644 (file)
@@ -825,7 +825,7 @@ static void __init rx1950_reserve(void)
 
 MACHINE_START(RX1950, "HP iPAQ RX1950")
     /* Maintainers: Vasily Khoruzhick */
-       .boot_params = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset = 0x100,
        .map_io = rx1950_map_io,
        .reserve        = rx1950_reserve,
        .init_irq = s3c24xx_init_irq,
index 1472b1a..e19499c 100644 (file)
@@ -218,7 +218,7 @@ static void __init rx3715_init_machine(void)
 
 MACHINE_START(RX3715, "IPAQ-RX3715")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
        .map_io         = rx3715_map_io,
        .reserve        = rx3715_reserve,
        .init_irq       = rx3715_init_irq,
index eedfe0f..36eeb41 100644 (file)
@@ -175,7 +175,7 @@ static void __init smdk2440_machine_init(void)
 
 MACHINE_START(S3C2440, "SMDK2440")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2440_map_io,
index 514275e..bec107e 100644 (file)
@@ -139,7 +139,7 @@ static void __init smdk2443_machine_init(void)
 
 MACHINE_START(SMDK2443, "SMDK2443")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2443_map_io,
index 374e45e..8dc0576 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
 
 #include <mach/hardware.h>
 #include <mach/map.h>
@@ -145,6 +146,7 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
        /* initialise the io descriptors we need for initialisation */
        iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
        iotable_init(mach_desc, size);
+       init_consistent_dma_size(SZ_8M);
 
        idcode = __raw_readl(S3C_VA_SYS + 0x118);
        if (!idcode) {
index 4760cda..b704669 100644 (file)
@@ -15,6 +15,4 @@
 
 #define PLAT_PHYS_OFFSET     UL(0x50000000)
 
-#define CONSISTENT_DMA_SIZE    SZ_8M
-
 #endif
index cb88643..d164a28 100644 (file)
@@ -233,7 +233,7 @@ static void __init anw6410_machine_init(void)
 
 MACHINE_START(ANW6410, "A&W6410")
        /* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s3c6410_init_irq,
        .map_io         = anw6410_map_io,
index af0c2fe..4c76e08 100644 (file)
@@ -766,7 +766,7 @@ static void __init crag6410_machine_init(void)
 
 MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
        /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = crag6410_map_io,
        .init_machine   = crag6410_machine_init,
index b3d93cc..19a0887 100644 (file)
@@ -265,7 +265,7 @@ static void __init hmt_machine_init(void)
 
 MACHINE_START(HMT, "Airgoo-HMT")
        /* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = hmt_map_io,
        .init_machine   = hmt_machine_init,
index 527f49b..e91f63f 100644 (file)
@@ -349,7 +349,7 @@ static void __init mini6410_machine_init(void)
 
 MACHINE_START(MINI6410, "MINI6410")
        /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = mini6410_map_io,
        .init_machine   = mini6410_machine_init,
index 01c6857..c30f2e5 100644 (file)
@@ -97,7 +97,7 @@ static void __init ncp_machine_init(void)
 
 MACHINE_START(NCP, "NCP")
        /* Maintainer: Samsung Electronics */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = ncp_map_io,
        .init_machine   = ncp_machine_init,
index 95b04b1..10870cb 100644 (file)
@@ -329,7 +329,7 @@ static void __init real6410_machine_init(void)
 
 MACHINE_START(REAL6410, "REAL6410")
        /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s3c6410_init_irq,
        .map_io         = real6410_map_io,
index 342e8df..cbb57de 100644 (file)
@@ -146,7 +146,7 @@ static void __init smartq5_machine_init(void)
 
 MACHINE_START(SMARTQ5, "SmartQ 5")
        /* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = smartq_map_io,
        .init_machine   = smartq5_machine_init,
index 5796397..04f914b 100644 (file)
@@ -162,7 +162,7 @@ static void __init smartq7_machine_init(void)
 
 MACHINE_START(SMARTQ7, "SmartQ 7")
        /* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s3c6410_init_irq,
        .map_io         = smartq_map_io,
        .init_machine   = smartq7_machine_init,
index 3cca642..6fd5e95 100644 (file)
@@ -85,7 +85,7 @@ static void __init smdk6400_machine_init(void)
 
 MACHINE_START(SMDK6400, "SMDK6400")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s3c6400_init_irq,
        .map_io         = smdk6400_map_io,
index ecbea92..dcf2d73 100644 (file)
@@ -742,7 +742,7 @@ static void __init smdk6410_machine_init(void)
 
 MACHINE_START(SMDK6410, "SMDK6410")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s3c6410_init_irq,
        .map_io         = smdk6410_map_io,
index 8bad643..055e285 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/suspend.h>
 #include <linux/serial_core.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
index a5c0095..8a93854 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -111,6 +112,7 @@ void __init s5p6440_map_io(void)
 
        iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
        iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+       init_consistent_dma_size(SZ_8M);
 }
 
 void __init s5p6450_map_io(void)
@@ -120,6 +122,7 @@ void __init s5p6450_map_io(void)
 
        iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
        iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
+       init_consistent_dma_size(SZ_8M);
 }
 
 /*
index 365a6eb..b14cbc3 100644 (file)
@@ -14,6 +14,5 @@
 #define __ASM_ARCH_MEMORY_H __FILE__
 
 #define PLAT_PHYS_OFFSET               UL(0x20000000)
-#define CONSISTENT_DMA_SIZE    SZ_8M
 
 #endif /* __ASM_ARCH_MEMORY_H */
index 69ed454..fe7380f 100644 (file)
@@ -129,7 +129,7 @@ static int s5p64x0_alloc_gc(void)
        }
 
        ct = gc->chip_types;
-       ct->chip.irq_ack = irq_gc_ack;
+       ct->chip.irq_ack = irq_gc_ack_set_bit;
        ct->chip.irq_mask = irq_gc_mask_set_bit;
        ct->chip.irq_unmask = irq_gc_mask_clr_bit;
        ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
index 346f8df..3b84e9b 100644 (file)
@@ -171,7 +171,7 @@ static void __init smdk6440_machine_init(void)
 
 MACHINE_START(SMDK6440, "SMDK6440")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .boot_params    = S5P64X0_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s5p6440_init_irq,
        .map_io         = smdk6440_map_io,
index 33f2adf..d99d29b 100644 (file)
@@ -190,7 +190,7 @@ static void __init smdk6450_machine_init(void)
 
 MACHINE_START(SMDK6450, "SMDK6450")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .boot_params    = S5P64X0_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
 
        .init_irq       = s5p6450_init_irq,
        .map_io         = smdk6450_map_io,
index 227d890..688f45b 100644 (file)
@@ -254,7 +254,7 @@ static void __init smdkc100_machine_init(void)
 
 MACHINE_START(SMDKC100, "SMDKC100")
        /* Maintainer: Byungho Min <bhmin@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s5pc100_init_irq,
        .map_io         = smdkc100_map_io,
        .init_machine   = smdkc100_machine_init,
index 79907ec..9114572 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -119,6 +120,7 @@ static void s5pv210_sw_reset(void)
 void __init s5pv210_map_io(void)
 {
        iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
+       init_consistent_dma_size(14 << 20);
 
        /* initialise device information early */
        s5pv210_default_sdhci0();
index 7b5fcf0..2d3cfa2 100644 (file)
@@ -14,7 +14,6 @@
 #define __ASM_ARCH_MEMORY_H
 
 #define PLAT_PHYS_OFFSET               UL(0x20000000)
-#define CONSISTENT_DMA_SIZE    (SZ_8M + SZ_4M + SZ_2M)
 
 /*
  * Sparsemem support
index 509627f..5811a96 100644 (file)
@@ -678,7 +678,7 @@ MACHINE_START(AQUILA, "Aquila")
        /* Maintainers:
           Marek Szyprowski <m.szyprowski@samsung.com>
           Kyungmin Park <kyungmin.park@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = aquila_map_io,
        .init_machine   = aquila_machine_init,
index 85c2d51..061cc7e 100644 (file)
@@ -897,7 +897,7 @@ static void __init goni_machine_init(void)
 
 MACHINE_START(GONI, "GONI")
        /* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = goni_map_io,
        .init_machine   = goni_machine_init,
index 6c412c8..f7266bb 100644 (file)
@@ -136,7 +136,7 @@ static void __init smdkc110_machine_init(void)
 
 MACHINE_START(SMDKC110, "SMDKC110")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = smdkc110_map_io,
        .init_machine   = smdkc110_machine_init,
index 5e011fc..e73e3b6 100644 (file)
@@ -319,7 +319,7 @@ static void __init smdkv210_machine_init(void)
 
 MACHINE_START(SMDKV210, "SMDKV210")
        /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = smdkv210_map_io,
        .init_machine   = smdkv210_machine_init,
index 925fc0d..97cc066 100644 (file)
@@ -125,7 +125,7 @@ static void __init torbreck_machine_init(void)
 
 MACHINE_START(TORBRECK, "TORBRECK")
        /* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
-       .boot_params    = S5P_PA_SDRAM + 0x100,
+       .atag_offset    = 0x100,
        .init_irq       = s5pv210_init_irq,
        .map_io         = torbreck_map_io,
        .init_machine   = torbreck_machine_init,
index 309e388..f149d27 100644 (file)
@@ -88,7 +88,7 @@ static struct sleep_save s5pv210_core_save[] = {
        SAVE_ITEM(S3C2410_TCNTO(0)),
 };
 
-void s5pv210_cpu_suspend(unsigned long arg)
+static int s5pv210_cpu_suspend(unsigned long arg)
 {
        unsigned long tmp;
 
index 26257df..d40da5f 100644 (file)
@@ -447,7 +447,7 @@ static void __init assabet_map_io(void)
 
 
 MACHINE_START(ASSABET, "Intel-Assabet")
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .fixup          = fixup_assabet,
        .map_io         = assabet_map_io,
        .init_irq       = sa1100_init_irq,
index b4311b0..bda83e1 100644 (file)
@@ -302,7 +302,7 @@ static void __init badge4_map_io(void)
 }
 
 MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = badge4_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index 03d7376..b30733a 100644 (file)
@@ -84,7 +84,7 @@ static void __init h3100_mach_init(void)
 }
 
 MACHINE_START(H3100, "Compaq iPAQ H3100")
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = h3100_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index 965f64a..6fd324d 100644 (file)
@@ -125,7 +125,7 @@ static void __init h3600_mach_init(void)
 }
 
 MACHINE_START(H3600, "Compaq iPAQ H3600")
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = h3600_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index db5e434..30f4a55 100644 (file)
@@ -195,7 +195,7 @@ static void __init hackkit_init(void)
  */
 
 MACHINE_START(HACKKIT, "HackKit Cpu Board")
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = hackkit_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index 176c066..0bb520d 100644 (file)
@@ -364,7 +364,7 @@ static void __init jornada720_mach_init(void)
 
 MACHINE_START(JORNADA720, "HP Jornada 720")
        /* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = jornada720_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index 7b9556b..5bc59d0 100644 (file)
@@ -61,7 +61,7 @@ static void __init lart_map_io(void)
 }
 
 MACHINE_START(LART, "LART")
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = lart_map_io,
        .init_irq       = sa1100_init_irq,
        .init_machine   = lart_init,
index 72087f0..032f388 100644 (file)
@@ -111,7 +111,7 @@ static void __init nanoengine_init(void)
 }
 
 MACHINE_START(NANOENGINE, "BSE nanoEngine")
-       .boot_params    = 0xc0000000,
+       .atag_offset    = 0x100,
        .map_io         = nanoengine_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index 7917b24..1cccbf5 100644 (file)
@@ -82,7 +82,7 @@ static void __init shannon_map_io(void)
 }
 
 MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = shannon_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index cfb7607..a1c2427 100644 (file)
@@ -229,7 +229,7 @@ arch_initcall(simpad_init);
 
 MACHINE_START(SIMPAD, "Simpad")
        /* Maintainer: Holger Freyther */
-       .boot_params    = 0xc0000100,
+       .atag_offset    = 0x100,
        .map_io         = simpad_map_io,
        .init_irq       = sa1100_init_irq,
        .timer          = &sa1100_timer,
index ac2873c..feda3ca 100644 (file)
@@ -152,7 +152,7 @@ static struct sys_timer shark_timer = {
 
 MACHINE_START(SHARK, "Shark")
        /* Maintainer: Alexander Schulz */
-       .boot_params    = 0x08003000,
+       .atag_offset    = 0x3000,
        .map_io         = shark_map_io,
        .init_irq       = shark_init_irq,
        .timer          = &shark_timer,
index ce5c251..5fde49d 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/sh_clk.h>
+#include <linux/dma-mapping.h>
 #include <video/sh_mobile_lcdc.h>
 #include <video/sh_mipi_dsi.h>
 #include <sound/sh_fsi.h>
@@ -341,6 +342,7 @@ static struct platform_device mipidsi0_device = {
 static struct sh_mobile_sdhi_info sdhi0_info = {
        .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
        .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
+       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
        .tmio_caps      = MMC_CAP_SD_HIGHSPEED,
        .tmio_ocr_mask  = MMC_VDD_27_28 | MMC_VDD_28_29,
 };
@@ -382,7 +384,7 @@ void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state)
 }
 
 static struct sh_mobile_sdhi_info sh_sdhi1_info = {
-       .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE,
+       .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
        .tmio_caps      = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
        .tmio_ocr_mask  = MMC_VDD_32_33 | MMC_VDD_33_34,
        .set_pwr        = ag5evm_sdhi1_set_pwr,
@@ -446,6 +448,8 @@ static struct map_desc ag5evm_io_desc[] __initdata = {
 static void __init ag5evm_map_io(void)
 {
        iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc));
+       /* DMA memory at 0xf6000000 - 0xffdfffff */
+       init_consistent_dma_size(158 << 20);
 
        /* setup early devices and console here as well */
        sh73a0_add_early_devices();
index 9e0856b..b622d8d 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/leds.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/dma-mapping.h>
 
 #include <media/sh_mobile_ceu.h>
 #include <media/sh_mobile_csi2.h>
@@ -1170,6 +1171,8 @@ static struct map_desc ap4evb_io_desc[] __initdata = {
 static void __init ap4evb_map_io(void)
 {
        iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc));
+       /* DMA memory at 0xf6000000 - 0xffdfffff */
+       init_consistent_dma_size(158 << 20);
 
        /* setup early devices and console here as well */
        sh7372_add_early_devices();
@@ -1412,6 +1415,7 @@ static void __init ap4evb_init(void)
        fsi_init_pm_clock();
        sh7372_pm_init();
        pm_clk_add(&fsi_device.dev, "spu2");
+       pm_clk_add(&lcdc1_device.dev, "hdmi");
 }
 
 static void __init ap4evb_timer_init(void)
index ef4613b..8b620bf 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/dma-mapping.h>
 #include <mach/sh7367.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
@@ -260,6 +261,8 @@ static struct map_desc g3evm_io_desc[] __initdata = {
 static void __init g3evm_map_io(void)
 {
        iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc));
+       /* DMA memory at 0xf6000000 - 0xffdfffff */
+       init_consistent_dma_size(158 << 20);
 
        /* setup early devices and console here as well */
        sh7367_add_early_devices();
index 8e3c555..7719ddc 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/gpio.h>
+#include <linux/dma-mapping.h>
 #include <mach/sh7377.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
@@ -274,6 +275,8 @@ static struct map_desc g4evm_io_desc[] __initdata = {
 static void __init g4evm_map_io(void)
 {
        iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc));
+       /* DMA memory at 0xf6000000 - 0xffdfffff */
+       init_consistent_dma_size(158 << 20);
 
        /* setup early devices and console here as well */
        sh7377_add_early_devices();
index d41c01f..de2253d 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/tca6416_keypad.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/renesas_usbhs.h>
+#include <linux/dma-mapping.h>
 
 #include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
@@ -641,6 +642,8 @@ static struct usbhs_private usbhs0_private = {
                },
                .driver_param = {
                        .buswait_bwait  = 4,
+                       .d0_tx_id       = SHDMA_SLAVE_USB0_TX,
+                       .d1_rx_id       = SHDMA_SLAVE_USB0_RX,
                },
        },
 };
@@ -810,6 +813,8 @@ static struct usbhs_private usbhs1_private = {
                        .buswait_bwait  = 4,
                        .pipe_type      = usbhs1_pipe_cfg,
                        .pipe_size      = ARRAY_SIZE(usbhs1_pipe_cfg),
+                       .d0_tx_id       = SHDMA_SLAVE_USB1_TX,
+                       .d1_rx_id       = SHDMA_SLAVE_USB1_RX,
                },
        },
 };
@@ -1377,6 +1382,8 @@ static struct map_desc mackerel_io_desc[] __initdata = {
 static void __init mackerel_map_io(void)
 {
        iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc));
+       /* DMA memory at 0xf6000000 - 0xffdfffff */
+       init_consistent_dma_size(158 << 20);
 
        /* setup early devices and console here as well */
        sh7372_add_early_devices();
@@ -1588,6 +1595,7 @@ static void __init mackerel_init(void)
        hdmi_init_pm_clock();
        sh7372_pm_init();
        pm_clk_add(&fsi_device.dev, "spu2");
+       pm_clk_add(&hdmi_lcdc_device.dev, "hdmi");
 }
 
 static void __init mackerel_timer_init(void)
index 6b1619a..6697592 100644 (file)
@@ -503,16 +503,17 @@ static struct clk *late_main_clks[] = {
        &sh7372_fsidivb_clk,
 };
 
-enum { MSTP001,
+enum { MSTP001, MSTP000,
        MSTP131, MSTP130,
        MSTP129, MSTP128, MSTP127, MSTP126, MSTP125,
        MSTP118, MSTP117, MSTP116, MSTP113,
        MSTP106, MSTP101, MSTP100,
        MSTP223,
-       MSTP218, MSTP217, MSTP216,
-       MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-       MSTP329, MSTP328, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312,
-       MSTP423, MSTP415, MSTP413, MSTP411, MSTP410, MSTP406, MSTP403,
+       MSTP218, MSTP217, MSTP216, MSTP214, MSTP208, MSTP207,
+       MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+       MSTP328, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312,
+       MSTP423, MSTP415, MSTP413, MSTP411, MSTP410, MSTP407, MSTP406,
+       MSTP405, MSTP404, MSTP403, MSTP400,
        MSTP_NR };
 
 #define MSTP(_parent, _reg, _bit, _flags) \
@@ -520,6 +521,7 @@ enum { MSTP001,
 
 static struct clk mstp_clks[MSTP_NR] = {
        [MSTP001] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 1, 0), /* IIC2 */
+       [MSTP000] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 0, 0), /* MSIOF0 */
        [MSTP131] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 31, 0), /* VEU3 */
        [MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */
        [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */
@@ -538,14 +540,16 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */
        [MSTP217] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */
        [MSTP216] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */
+       [MSTP214] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */
+       [MSTP208] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 8, 0), /* MSIOF1 */
        [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
        [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
+       [MSTP205] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 5, 0), /* MSIOF2 */
        [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
        [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
        [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
        [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
        [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
-       [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
        [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSI2 */
        [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
        [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
@@ -557,8 +561,12 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP413] = MSTP(&pllc1_div2_clk, SMSTPCR4, 13, 0), /* HDMI */
        [MSTP411] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 11, 0), /* IIC3 */
        [MSTP410] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 10, 0), /* IIC4 */
+       [MSTP407] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-DMAC1 */
        [MSTP406] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 6, 0), /* USB1 */
+       [MSTP405] = MSTP(&r_clk, SMSTPCR4, 5, 0), /* CMT4 */
+       [MSTP404] = MSTP(&r_clk, SMSTPCR4, 4, 0), /* CMT3 */
        [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
+       [MSTP400] = MSTP(&r_clk, SMSTPCR4, 0, 0), /* CMT2 */
 };
 
 static struct clk_lookup lookups[] = {
@@ -609,6 +617,7 @@ static struct clk_lookup lookups[] = {
 
        /* MSTP32 clocks */
        CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
+       CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[MSTP000]), /* MSIOF0 */
        CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
        CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
        CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */
@@ -629,14 +638,16 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* DMAC1 */
        CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* DMAC2 */
        CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), /* DMAC3 */
+       CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]), /* USB-DMAC0 */
+       CLKDEV_DEV_ID("spi_sh_msiof.1", &mstp_clks[MSTP208]), /* MSIOF1 */
        CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
        CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP206]), /* SCIFB */
+       CLKDEV_DEV_ID("spi_sh_msiof.2", &mstp_clks[MSTP205]), /* MSIOF2 */
        CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
        CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
        CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
        CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
        CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
-       CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
        CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
        CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
        CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
@@ -650,11 +661,17 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */
        CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */
        CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */
+       CLKDEV_DEV_ID("sh-dma-engine.4", &mstp_clks[MSTP407]), /* USB-DMAC1 */
        CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
        CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
        CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[MSTP406]), /* USB1 */
+       CLKDEV_DEV_ID("sh_cmt.4", &mstp_clks[MSTP405]), /* CMT4 */
+       CLKDEV_DEV_ID("sh_cmt.3", &mstp_clks[MSTP404]), /* CMT3 */
        CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
+       CLKDEV_DEV_ID("sh_cmt.2", &mstp_clks[MSTP400]), /* CMT2 */
 
+       CLKDEV_ICK_ID("hdmi", "sh_mobile_lcdc_fb.1",
+                     &div6_reparent_clks[DIV6_HDMI]),
        CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
        CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
        CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
index 6db2cca..61a846b 100644 (file)
@@ -365,7 +365,7 @@ void __init sh73a0_clock_init(void)
        __raw_writel(0x108, SD2CKCR);
 
        /* detect main clock parent */
-       switch ((__raw_readl(CKSCR) >> 24) & 0x03) {
+       switch ((__raw_readl(CKSCR) >> 28) & 0x03) {
        case 0:
                main_clk.parent = &sh73a0_extal1_clk;
                break;
index ad00c3c..0ffbe81 100644 (file)
@@ -4,7 +4,4 @@
 #define PLAT_PHYS_OFFSET       UL(CONFIG_MEMORY_START)
 #define MEM_SIZE       UL(CONFIG_MEMORY_SIZE)
 
-/* DMA memory at 0xf6000000 - 0xffdfffff */
-#define CONSISTENT_DMA_SIZE (158 << 20)
-
 #endif /* __ASM_MACH_MEMORY_H */
index ce595ce..24e63a8 100644 (file)
@@ -459,6 +459,10 @@ enum {
        SHDMA_SLAVE_SDHI2_TX,
        SHDMA_SLAVE_MMCIF_RX,
        SHDMA_SLAVE_MMCIF_TX,
+       SHDMA_SLAVE_USB0_TX,
+       SHDMA_SLAVE_USB0_RX,
+       SHDMA_SLAVE_USB1_TX,
+       SHDMA_SLAVE_USB1_RX,
 };
 
 extern struct clk sh7372_extal1_clk;
index 3b28743..739315e 100644 (file)
@@ -379,7 +379,7 @@ enum {
        /* BBIF2 */
        VPU,
        TSIF1,
-       _3DG_SGX530,
+       /* 3DG */
        _2DDMAC,
        IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
        IPMMU_IPMMUR, IPMMU_IPMMUR2,
@@ -436,7 +436,7 @@ static struct intc_vect intcs_vectors[] = {
        /* BBIF2 */
        INTCS_VECT(VPU, 0x980),
        INTCS_VECT(TSIF1, 0x9a0),
-       INTCS_VECT(_3DG_SGX530, 0x9e0),
+       /* 3DG */
        INTCS_VECT(_2DDMAC, 0xa00),
        INTCS_VECT(IIC2_ALI2, 0xa80), INTCS_VECT(IIC2_TACKI2, 0xaa0),
        INTCS_VECT(IIC2_WAITI2, 0xac0), INTCS_VECT(IIC2_DTEI2, 0xae0),
@@ -521,7 +521,7 @@ static struct intc_mask_reg intcs_mask_registers[] = {
            RTDMAC_1_DEI3, RTDMAC_1_DEI2, RTDMAC_1_DEI1, RTDMAC_1_DEI0 } },
        { 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */
          { 0, 0, MSIOF, 0,
-           _3DG_SGX530, 0, 0, 0 } },
+           0, 0, 0, 0 } },
        { 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */
          { 0, TMU_TUNI2, TMU_TUNI1, TMU_TUNI0,
            0, 0, 0, 0 } },
@@ -561,7 +561,6 @@ static struct intc_prio_reg intcs_prio_registers[] = {
                                              TMU_TUNI2, TSIF1 } },
        { 0xffd2001c, 0, 16, 4, /* IPRHS */ { 0, 0, VEU, BEU } },
        { 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF0, IIC0 } },
-       { 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, _3DG_SGX530, 0, 0 } },
        { 0xffd20028, 0, 16, 4, /* IPRKS */ { 0, 0, LMB, 0 } },
        { 0xffd2002c, 0, 16, 4, /* IPRLS */ { IPMMU, 0, 0, 0 } },
        { 0xffd20030, 0, 16, 4, /* IPRMS */ { IIC2, 0, 0, 0 } },
index 79f0413..2d9b1b1 100644 (file)
@@ -169,35 +169,35 @@ static struct platform_device scif6_device = {
 };
 
 /* CMT */
-static struct sh_timer_config cmt10_platform_data = {
-       .name = "CMT10",
-       .channel_offset = 0x10,
-       .timer_bit = 0,
+static struct sh_timer_config cmt2_platform_data = {
+       .name = "CMT2",
+       .channel_offset = 0x40,
+       .timer_bit = 5,
        .clockevent_rating = 125,
        .clocksource_rating = 125,
 };
 
-static struct resource cmt10_resources[] = {
+static struct resource cmt2_resources[] = {
        [0] = {
-               .name   = "CMT10",
-               .start  = 0xe6138010,
-               .end    = 0xe613801b,
+               .name   = "CMT2",
+               .start  = 0xe6130040,
+               .end    = 0xe613004b,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = evt2irq(0x0b00), /* CMT1_CMT10 */
+               .start  = evt2irq(0x0b80), /* CMT2 */
                .flags  = IORESOURCE_IRQ,
        },
 };
 
-static struct platform_device cmt10_device = {
+static struct platform_device cmt2_device = {
        .name           = "sh_cmt",
-       .id             = 10,
+       .id             = 2,
        .dev = {
-               .platform_data  = &cmt10_platform_data,
+               .platform_data  = &cmt2_platform_data,
        },
-       .resource       = cmt10_resources,
-       .num_resources  = ARRAY_SIZE(cmt10_resources),
+       .resource       = cmt2_resources,
+       .num_resources  = ARRAY_SIZE(cmt2_resources),
 };
 
 /* TMU */
@@ -602,6 +602,150 @@ static struct platform_device dma2_device = {
        },
 };
 
+/*
+ * USB-DMAC
+ */
+
+unsigned int usbts_shift[] = {3, 4, 5};
+
+enum {
+       XMIT_SZ_8BYTE           = 0,
+       XMIT_SZ_16BYTE          = 1,
+       XMIT_SZ_32BYTE          = 2,
+};
+
+#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
+
+static const struct sh_dmae_channel sh7372_usb_dmae_channels[] = {
+       {
+               .offset = 0,
+       }, {
+               .offset = 0x20,
+       },
+};
+
+/* USB DMAC0 */
+static const struct sh_dmae_slave_config sh7372_usb_dmae0_slaves[] = {
+       {
+               .slave_id       = SHDMA_SLAVE_USB0_TX,
+               .chcr           = USBTS_INDEX2VAL(XMIT_SZ_8BYTE),
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB0_RX,
+               .chcr           = USBTS_INDEX2VAL(XMIT_SZ_8BYTE),
+       },
+};
+
+static struct sh_dmae_pdata usb_dma0_platform_data = {
+       .slave          = sh7372_usb_dmae0_slaves,
+       .slave_num      = ARRAY_SIZE(sh7372_usb_dmae0_slaves),
+       .channel        = sh7372_usb_dmae_channels,
+       .channel_num    = ARRAY_SIZE(sh7372_usb_dmae_channels),
+       .ts_low_shift   = 6,
+       .ts_low_mask    = 0xc0,
+       .ts_high_shift  = 0,
+       .ts_high_mask   = 0,
+       .ts_shift       = usbts_shift,
+       .ts_shift_num   = ARRAY_SIZE(usbts_shift),
+       .dmaor_init     = DMAOR_DME,
+       .chcr_offset    = 0x14,
+       .chcr_ie_bit    = 1 << 5,
+       .dmaor_is_32bit = 1,
+       .needs_tend_set = 1,
+       .no_dmars       = 1,
+};
+
+static struct resource sh7372_usb_dmae0_resources[] = {
+       {
+               /* Channel registers and DMAOR */
+               .start  = 0xe68a0020,
+               .end    = 0xe68a0064 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               /* VCR/SWR/DMICR */
+               .start  = 0xe68a0000,
+               .end    = 0xe68a0014 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               /* IRQ for channels */
+               .start  = evt2irq(0x0a00),
+               .end    = evt2irq(0x0a00),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device usb_dma0_device = {
+       .name           = "sh-dma-engine",
+       .id             = 3,
+       .resource       = sh7372_usb_dmae0_resources,
+       .num_resources  = ARRAY_SIZE(sh7372_usb_dmae0_resources),
+       .dev            = {
+               .platform_data  = &usb_dma0_platform_data,
+       },
+};
+
+/* USB DMAC1 */
+static const struct sh_dmae_slave_config sh7372_usb_dmae1_slaves[] = {
+       {
+               .slave_id       = SHDMA_SLAVE_USB1_TX,
+               .chcr           = USBTS_INDEX2VAL(XMIT_SZ_8BYTE),
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB1_RX,
+               .chcr           = USBTS_INDEX2VAL(XMIT_SZ_8BYTE),
+       },
+};
+
+static struct sh_dmae_pdata usb_dma1_platform_data = {
+       .slave          = sh7372_usb_dmae1_slaves,
+       .slave_num      = ARRAY_SIZE(sh7372_usb_dmae1_slaves),
+       .channel        = sh7372_usb_dmae_channels,
+       .channel_num    = ARRAY_SIZE(sh7372_usb_dmae_channels),
+       .ts_low_shift   = 6,
+       .ts_low_mask    = 0xc0,
+       .ts_high_shift  = 0,
+       .ts_high_mask   = 0,
+       .ts_shift       = usbts_shift,
+       .ts_shift_num   = ARRAY_SIZE(usbts_shift),
+       .dmaor_init     = DMAOR_DME,
+       .chcr_offset    = 0x14,
+       .chcr_ie_bit    = 1 << 5,
+       .dmaor_is_32bit = 1,
+       .needs_tend_set = 1,
+       .no_dmars       = 1,
+};
+
+static struct resource sh7372_usb_dmae1_resources[] = {
+       {
+               /* Channel registers and DMAOR */
+               .start  = 0xe68c0020,
+               .end    = 0xe68c0064 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               /* VCR/SWR/DMICR */
+               .start  = 0xe68c0000,
+               .end    = 0xe68c0014 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               /* IRQ for channels */
+               .start  = evt2irq(0x1d00),
+               .end    = evt2irq(0x1d00),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device usb_dma1_device = {
+       .name           = "sh-dma-engine",
+       .id             = 4,
+       .resource       = sh7372_usb_dmae1_resources,
+       .num_resources  = ARRAY_SIZE(sh7372_usb_dmae1_resources),
+       .dev            = {
+               .platform_data  = &usb_dma1_platform_data,
+       },
+};
+
 /* VPU */
 static struct uio_info vpu_platform_data = {
        .name = "VPU5HG",
@@ -818,7 +962,7 @@ static struct platform_device *sh7372_early_devices[] __initdata = {
        &scif4_device,
        &scif5_device,
        &scif6_device,
-       &cmt10_device,
+       &cmt2_device,
        &tmu00_device,
        &tmu01_device,
 };
@@ -829,6 +973,8 @@ static struct platform_device *sh7372_late_devices[] __initdata = {
        &dma0_device,
        &dma1_device,
        &dma2_device,
+       &usb_dma0_device,
+       &usb_dma1_device,
        &vpu_device,
        &veu0_device,
        &veu1_device,
index 69006f6..a5ff98e 100644 (file)
@@ -64,7 +64,7 @@ static void __init spear300_evb_init(void)
 }
 
 MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
-       .boot_params    =       0x00000100,
+       .atag_offset    =       0x100,
        .map_io         =       spear3xx_map_io,
        .init_irq       =       spear3xx_init_irq,
        .timer          =       &spear3xx_timer,
index c8684ce..45d180d 100644 (file)
@@ -70,7 +70,7 @@ static void __init spear310_evb_init(void)
 }
 
 MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
-       .boot_params    =       0x00000100,
+       .atag_offset    =       0x100,
        .map_io         =       spear3xx_map_io,
        .init_irq       =       spear3xx_init_irq,
        .timer          =       &spear3xx_timer,
index a12b353..2287984 100644 (file)
@@ -68,7 +68,7 @@ static void __init spear320_evb_init(void)
 }
 
 MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
-       .boot_params    =       0x00000100,
+       .atag_offset    =       0x100,
        .map_io         =       spear3xx_map_io,
        .init_irq       =       spear3xx_init_irq,
        .timer          =       &spear3xx_timer,
index f19cefe..8238fe3 100644 (file)
@@ -43,7 +43,7 @@ static void __init spear600_evb_init(void)
 }
 
 MACHINE_START(SPEAR600, "ST-SPEAR600-EVB")
-       .boot_params    =       0x00000100,
+       .atag_offset    =       0x100,
        .map_io         =       spear6xx_map_io,
        .init_irq       =       spear6xx_init_irq,
        .timer          =       &spear6xx_timer,
index 4cb3c2d..777a5bb 100644 (file)
@@ -73,7 +73,7 @@ static void __init tcc8k_map_io(void)
 }
 
 MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
-       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = tcc8k_map_io,
        .init_irq       = tcc8k_init_irq,
        .init_machine   = tcc8k_init,
index 846cd7d..a4d1980 100644 (file)
@@ -179,7 +179,7 @@ static void __init tegra_harmony_init(void)
 }
 
 MACHINE_START(HARMONY, "harmony")
-       .boot_params  = 0x00000100,
+       .atag_offset    = 0x100,
        .fixup          = tegra_harmony_fixup,
        .map_io         = tegra_map_common_io,
        .init_early     = tegra_init_early,
index ea2f79c..3197c4c 100644 (file)
@@ -127,7 +127,7 @@ static void __init tegra_paz00_init(void)
 }
 
 MACHINE_START(PAZ00, "Toshiba AC100 / Dynabook AZ")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .fixup          = tegra_paz00_fixup,
        .map_io         = tegra_map_common_io,
        .init_early     = tegra_init_early,
index 56cbabf..9e98ac7 100644 (file)
@@ -201,7 +201,7 @@ static void __init tegra_wario_init(void)
 
 
 MACHINE_START(SEABOARD, "seaboard")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = tegra_map_common_io,
        .init_early     = tegra_init_early,
        .init_irq       = tegra_init_irq,
@@ -210,7 +210,7 @@ MACHINE_START(SEABOARD, "seaboard")
 MACHINE_END
 
 MACHINE_START(KAEN, "kaen")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = tegra_map_common_io,
        .init_early     = tegra_init_early,
        .init_irq       = tegra_init_irq,
@@ -219,7 +219,7 @@ MACHINE_START(KAEN, "kaen")
 MACHINE_END
 
 MACHINE_START(WARIO, "wario")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = tegra_map_common_io,
        .init_early     = tegra_init_early,
        .init_irq       = tegra_init_irq,
index 89a6d2a..8489aa8 100644 (file)
@@ -171,7 +171,7 @@ static void __init tegra_trimslice_init(void)
 }
 
 MACHINE_START(TRIMSLICE, "trimslice")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .fixup          = tegra_trimslice_fixup,
        .map_io         = tegra_map_common_io,
        .init_early     = tegra_init_early,
index 399c89f..376b6df 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -92,6 +93,8 @@ static struct map_desc u300_io_desc[] __initdata = {
 void __init u300_map_io(void)
 {
        iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
+       /* We enable a real big DMA buffer if need be. */
+       init_consistent_dma_size(SZ_4M);
 }
 
 /*
index 888e2e3..7034bae 100644 (file)
@@ -16,7 +16,7 @@
 #ifdef CONFIG_MACH_U300_DUAL_RAM
 
 #define PLAT_PHYS_OFFSET               UL(0x48000000)
-#define BOOT_PARAMS_OFFSET     (PHYS_OFFSET + 0x100)
+#define BOOT_PARAMS_OFFSET             0x100
 
 #else
 
 #define PLAT_PHYS_OFFSET (0x28000000 + \
             (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
             (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
+#define BOOT_PARAMS_OFFSET (0x100 + \
+            (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1)*1024*1024*2)
 #else
 #define PLAT_PHYS_OFFSET (0x28000000 + \
             (CONFIG_MACH_U300_ACCESS_MEM_SIZE +        \
             (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
+#define BOOT_PARAMS_OFFSET 0x100
 #endif
-#define BOOT_PARAMS_OFFSET (0x28000000 + \
-           (CONFIG_MACH_U300_ACCESS_MEM_SIZE +         \
-           (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100)
 #endif
 
-/*
- * We enable a real big DMA buffer if need be.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
-
 #endif
index 48b3b7f..80e7305 100644 (file)
@@ -61,7 +61,7 @@ static void __init u300_init_machine(void)
 
 MACHINE_START(U300, MACH_U300_STRING)
        /* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
-       .boot_params    = BOOT_PARAMS_OFFSET,
+       .atag_offset    = BOOT_PARAMS_OFFSET,
        .map_io         = u300_map_io,
        .reserve        = u300_reserve,
        .init_irq       = u300_init_irq,
index cd54aba..2cc4876 100644 (file)
@@ -645,7 +645,7 @@ static void __init mop500_init_machine(void)
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
        /* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
-       .boot_params    = 0x100,
+       .atag_offset    = 0x100,
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
        /* we re-use nomadik timer here */
@@ -654,7 +654,7 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 MACHINE_END
 
 MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
-       .boot_params    = 0x100,
+       .atag_offset    = 0x100,
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
        .timer          = &ux500_timer,
@@ -662,7 +662,7 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
 MACHINE_END
 
 MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
-       .boot_params    = 0x100,
+       .atag_offset    = 0x100,
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
        /* we re-use nomadik timer here */
index e58f0f5..166d47a 100644 (file)
@@ -118,7 +118,7 @@ static void __init u5500_init_machine(void)
 }
 
 MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = u5500_map_io,
        .init_irq       = ux500_init_irq,
        .timer          = &ux500_timer,
index f8ae64b..fda4866 100644 (file)
@@ -35,7 +35,7 @@
 
 MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = versatile_map_io,
        .init_early     = versatile_init_early,
        .init_irq       = versatile_init_irq,
index 37c23df..feaf9cb 100644 (file)
@@ -103,7 +103,7 @@ static void __init versatile_pb_init(void)
 
 MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = versatile_map_io,
        .init_early     = versatile_init_early,
        .init_irq       = versatile_init_irq,
index d0d267a..1fafc32 100644 (file)
@@ -443,7 +443,7 @@ static void __init v2m_init(void)
 }
 
 MACHINE_START(VEXPRESS, "ARM-Versatile Express")
-       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+       .atag_offset    = 0x100,
        .map_io         = v2m_map_io,
        .init_early     = v2m_init_early,
        .init_irq       = v2m_init_irq,
index 94a261d..a464c75 100644 (file)
@@ -68,7 +68,7 @@ void __init bv07_init(void)
 }
 
 MACHINE_START(BV07, "Benign BV07 Mini Netbook")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .reserve        = vt8500_reserve_mem,
        .map_io         = vt8500_map_io,
        .init_irq       = vt8500_init_irq,
index e73aadb..cf910a9 100644 (file)
@@ -68,7 +68,7 @@ void __init wm8505_7in_init(void)
 }
 
 MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
-       .boot_params    = 0x00000100,
+       .atag_offset    = 0x100,
        .reserve        = wm8505_reserve_mem,
        .map_io         = wm8505_map_io,
        .init_irq       = wm8505_init_irq,
index 30fccde..31c1090 100644 (file)
@@ -34,7 +34,6 @@ static void __init nuc910evb_init(void)
 
 MACHINE_START(W90P910EVB, "W90P910EVB")
        /* Maintainer: Wan ZongShun */
-       .boot_params    = 0,
        .map_io         = nuc910evb_map_io,
        .init_irq       = nuc900_init_irq,
        .init_machine   = nuc910evb_init,
index 590c99b..4062e55 100644 (file)
@@ -37,7 +37,6 @@ static void __init nuc950evb_init(void)
 
 MACHINE_START(W90P950EVB, "W90P950EVB")
        /* Maintainer: Wan ZongShun */
-       .boot_params    = 0,
        .map_io         = nuc950evb_map_io,
        .init_irq       = nuc900_init_irq,
        .init_machine   = nuc950evb_init,
index e09c645..0ab9995 100644 (file)
@@ -34,7 +34,6 @@ static void __init nuc960evb_init(void)
 
 MACHINE_START(W90N960EVB, "W90N960EVB")
        /* Maintainer: Wan ZongShun */
-       .boot_params    = 0,
        .map_io         = nuc960evb_map_io,
        .init_irq       = nuc900_init_irq,
        .init_machine   = nuc960evb_init,
index 52162d5..2cbf68e 100644 (file)
@@ -17,7 +17,7 @@
        cmp     \tmp, # 0x5600                  @ Is it ldrsb?
        orreq   \tmp, \tmp, #1 << 11            @ Set L-bit if yes
        tst     \tmp, #1 << 11                  @ L = 0 -> write
-       orreq   \psr, \psr, #1 << 11            @ yes.
+       orreq   \fsr, \fsr, #1 << 11            @ yes.
        b       do_DataAbort
 not_thumb:
        .endm
index 44c0867..9ecfdb5 100644 (file)
@@ -277,6 +277,25 @@ static void l2x0_disable(void)
        spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
+static void __init l2x0_unlock(__u32 cache_id)
+{
+       int lockregs;
+       int i;
+
+       if (cache_id == L2X0_CACHE_ID_PART_L310)
+               lockregs = 8;
+       else
+               /* L210 and unknown types */
+               lockregs = 1;
+
+       for (i = 0; i < lockregs; i++) {
+               writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
+                              i * L2X0_LOCKDOWN_STRIDE);
+               writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
+                              i * L2X0_LOCKDOWN_STRIDE);
+       }
+}
+
 void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
 {
        __u32 aux;
@@ -328,6 +347,8 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
         * accessing the below registers will fault.
         */
        if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+               /* Make sure that I&D is not locked down when starting */
+               l2x0_unlock(cache_id);
 
                /* l2x0 controller is disabled */
                writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
index 0a0a1e7..50be842 100644 (file)
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/highmem.h>
+#include <linux/slab.h>
 
 #include <asm/memory.h>
 #include <asm/highmem.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
+#include <asm/mach/arch.h>
 
 #include "mm.h"
 
@@ -117,26 +119,37 @@ static void __dma_free_buffer(struct page *page, size_t size)
 }
 
 #ifdef CONFIG_MMU
-/* Sanity check size */
-#if (CONSISTENT_DMA_SIZE % SZ_2M)
-#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
-#endif
 
-#define CONSISTENT_OFFSET(x)   (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
-#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
-#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
+
+#define CONSISTENT_OFFSET(x)   (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT)
+#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PGDIR_SHIFT)
 
 /*
  * These are the page tables (2MB each) covering uncached, DMA consistent allocations
  */
-static pte_t *consistent_pte[NUM_CONSISTENT_PTES];
+static pte_t **consistent_pte;
+
+#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M
+
+unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
+
+void __init init_consistent_dma_size(unsigned long size)
+{
+       unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M);
+
+       BUG_ON(consistent_pte); /* Check we're called before DMA region init */
+       BUG_ON(base < VMALLOC_END);
+
+       /* Grow region to accommodate specified size  */
+       if (base < consistent_base)
+               consistent_base = base;
+}
 
 #include "vmregion.h"
 
 static struct arm_vmregion_head consistent_head = {
        .vm_lock        = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),
        .vm_list        = LIST_HEAD_INIT(consistent_head.vm_list),
-       .vm_start       = CONSISTENT_BASE,
        .vm_end         = CONSISTENT_END,
 };
 
@@ -155,7 +168,17 @@ static int __init consistent_init(void)
        pmd_t *pmd;
        pte_t *pte;
        int i = 0;
-       u32 base = CONSISTENT_BASE;
+       unsigned long base = consistent_base;
+       unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_SHIFT;
+
+       consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
+       if (!consistent_pte) {
+               pr_err("%s: no memory\n", __func__);
+               return -ENOMEM;
+       }
+
+       pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END);
+       consistent_head.vm_start = base;
 
        do {
                pgd = pgd_offset(&init_mm, base);
@@ -198,7 +221,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
        size_t align;
        int bit;
 
-       if (!consistent_pte[0]) {
+       if (!consistent_pte) {
                printk(KERN_ERR "%s: not initialised\n", __func__);
                dump_stack();
                return NULL;
index 91bca35..34409a0 100644 (file)
@@ -298,7 +298,7 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
-       return memblock_is_memory(pfn << PAGE_SHIFT);
+       return memblock_is_memory(__pfn_to_phys(pfn));
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
@@ -653,9 +653,6 @@ void __init mem_init(void)
                        "    ITCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 #endif
                        "    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
-#ifdef CONFIG_MMU
-                       "    DMA     : 0x%08lx - 0x%08lx   (%4ld MB)\n"
-#endif
                        "    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
                        "    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #ifdef CONFIG_HIGHMEM
@@ -674,9 +671,6 @@ void __init mem_init(void)
                        MLK(ITCM_OFFSET, (unsigned long) itcm_end),
 #endif
                        MLK(FIXADDR_START, FIXADDR_TOP),
-#ifdef CONFIG_MMU
-                       MLM(CONSISTENT_BASE, CONSISTENT_END),
-#endif
                        MLM(VMALLOC_START, VMALLOC_END),
                        MLM(PAGE_OFFSET, (unsigned long)high_memory),
 #ifdef CONFIG_HIGHMEM
@@ -699,9 +693,6 @@ void __init mem_init(void)
         * be detected at build time already.
         */
 #ifdef CONFIG_MMU
-       BUILD_BUG_ON(VMALLOC_END                        > CONSISTENT_BASE);
-       BUG_ON(VMALLOC_END                              > CONSISTENT_BASE);
-
        BUILD_BUG_ON(TASK_SIZE                          > MODULES_VADDR);
        BUG_ON(TASK_SIZE                                > MODULES_VADDR);
 #endif
index 11be5cd..3ec84b9 100644 (file)
 # endif
 #endif
 
-#if defined(CONFIG_MX3_VIDEO)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for mx3 camera driver to capture at least two QXGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_8M
-
-#elif defined(CONFIG_MX1_VIDEO) || defined(CONFIG_VIDEO_MX2_HOSTSUPPORT)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for i.MX camera driver to capture at least four VGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
-#endif /* CONFIG_MX1_VIDEO || CONFIG_VIDEO_MX2_HOSTSUPPORT */
-
 #endif /* __ASM_ARCH_MXC_MEMORY_H__ */
index d72ec85..ebe67ea 100644 (file)
@@ -309,6 +309,8 @@ extern void omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
 void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
 void omap_iounmap(volatile void __iomem *addr);
 
+extern void __init omap_init_consistent_dma_size(void);
+
 #endif
 
 #endif
index e6720aa..7f9df6f 100644 (file)
 
 #endif /* CONFIG_ARCH_OMAP15XX */
 
-/* Override the ARM default */
-#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-
-#if (CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE == 0)
-#undef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-#define CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE 2
-#endif
-
-#define CONSISTENT_DMA_SIZE \
-       (((CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE + 1) & ~1) * 1024 * 1024)
-
-#endif
-
 #endif
 
index f1ecfa9..e9b0e23 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
 
 #include <plat/omap7xx.h>
 #include <plat/omap1510.h>
@@ -139,3 +140,10 @@ void omap_iounmap(volatile void __iomem *addr)
                __iounmap(addr);
 }
 EXPORT_SYMBOL(omap_iounmap);
+
+void __init omap_init_consistent_dma_size(void)
+{
+#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
+       init_consistent_dma_size(CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE << 20);
+#endif
+}
index b6b4097..02609ee 100644 (file)
@@ -615,6 +615,9 @@ static int _od_resume_noirq(struct device *dev)
 
        return pm_generic_resume_noirq(dev);
 }
+#else
+#define _od_suspend_noirq NULL
+#define _od_resume_noirq NULL
 #endif
 
 static struct dev_pm_domain omap_device_pm_domain = {
@@ -622,7 +625,8 @@ static struct dev_pm_domain omap_device_pm_domain = {
                SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
                                   _od_runtime_idle)
                USE_PLATFORM_PM_SLEEP_OPS
-               SET_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq, _od_resume_noirq)
+               .suspend_noirq = _od_suspend_noirq,
+               .resume_noirq = _od_resume_noirq,
        }
 };
 
index 02af235..5f84a3f 100644 (file)
@@ -192,7 +192,7 @@ unsigned long s5p_spdif_get_rate(struct clk *clk)
        if (IS_ERR(pclk))
                return -EINVAL;
 
-       rate = pclk->ops->get_rate(clk);
+       rate = pclk->ops->get_rate(pclk);
        clk_put(pclk);
 
        return rate;
index 327ab9f..f71078e 100644 (file)
@@ -23,6 +23,8 @@
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 
+#include <asm/mach/irq.h>
+
 #define GPIO_BASE(chip)                (((unsigned long)(chip)->base) & 0xFFFFF000u)
 
 #define CON_OFFSET             0x700
@@ -81,6 +83,9 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
        int group, pend_offset, mask_offset;
        unsigned int pend, mask;
 
+       struct irq_chip *chip = irq_get_chip(irq);
+       chained_irq_enter(chip, desc);
+
        for (group = 0; group < bank->nr_groups; group++) {
                struct s3c_gpio_chip *chip = bank->chips[group];
                if (!chip)
@@ -102,6 +107,7 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
                        pend &= ~BIT(offset);
                }
        }
+       chained_irq_exit(chip, desc);
 }
 
 static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
index 51d8da8..ad530c7 100644 (file)
@@ -20,7 +20,7 @@ struct samsung_bl_gpio_info {
        int func;
 };
 
-extern void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
+extern void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
        struct platform_pwm_backlight_data *bl_data);
 
 #endif /* __ASM_PLAT_BACKLIGHT_H */
index f714d06..51583cd 100644 (file)
 #include <plat/irq-vic-timer.h>
 #include <plat/regs-timer.h>
 
+#include <asm/mach/irq.h>
+
 static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
 {
+       struct irq_chip *chip = irq_get_chip(irq);
+       chained_irq_enter(chip, desc);
        generic_handle_irq((int)desc->irq_data.handler_data);
+       chained_irq_exit(chip, desc);
 }
 
 /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
index c7fd394..6eba535 100644 (file)
@@ -158,7 +158,7 @@ sys_call_table:
        .long   sys_sched_rr_get_interval
        .long   sys_nanosleep
        .long   sys_poll
-       .long   sys_nfsservctl          /* 145 */
+       .long   sys_ni_syscall          /* 145 was nfsservctl */
        .long   sys_setresgid
        .long   sys_getresgid
        .long   sys_prctl
index 225d311..e413729 100644 (file)
@@ -1543,7 +1543,7 @@ ENTRY(_sys_call_table)
        .long _sys_ni_syscall   /* for vm86 */
        .long _sys_ni_syscall   /* old "query_module" */
        .long _sys_ni_syscall   /* sys_poll */
-       .long _sys_nfsservctl
+       .long _sys_ni_syscall   /* old nfsservctl */
        .long _sys_setresgid    /* setresgid16 */       /* 170 */
        .long _sys_getresgid    /* getresgid16 */
        .long _sys_prctl
index 1161883..592fbe9 100644 (file)
@@ -771,7 +771,7 @@ sys_call_table:
        .long sys_ni_syscall    /* sys_vm86 */
        .long sys_ni_syscall    /* Old sys_query_module */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall    /* old nfsservctl */
        .long sys_setresgid16   /* 170 */
        .long sys_getresgid16
        .long sys_prctl
index 84fed7e..c3ea469 100644 (file)
@@ -714,7 +714,7 @@ sys_call_table:
        .long sys_ni_syscall    /* sys_vm86 */
        .long sys_ni_syscall    /* Old sys_query_module */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall    /* Old nfsservctl */
        .long sys_setresgid16   /* 170 */
        .long sys_getresgid16
        .long sys_prctl
diff --git a/arch/cris/include/asm/serial.h b/arch/cris/include/asm/serial.h
new file mode 100644 (file)
index 0000000..af7535a
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ASM_SERIAL_H
+#define _ASM_SERIAL_H
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ */
+#define BASE_BAUD (1843200 / 16)
+
+#endif /* _ASM_SERIAL_H */
index 017d6d7..5ba23f7 100644 (file)
@@ -1358,7 +1358,7 @@ sys_call_table:
        .long sys_ni_syscall    /* for vm86 */
        .long sys_ni_syscall    /* Old sys_query_module */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall    /* Old nfsservctl */
        .long sys_setresgid16   /* 170 */
        .long sys_getresgid16
        .long sys_prctl
index f4b2e67..4be2ea2 100644 (file)
@@ -183,7 +183,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_ni_syscall)       /* for vm86 */
        .long SYMBOL_NAME(sys_ni_syscall)       /* sys_query_module */
        .long SYMBOL_NAME(sys_poll)
-       .long SYMBOL_NAME(sys_nfsservctl)
+       .long SYMBOL_NAME(sys_ni_syscall)       /* old nfsservctl */
        .long SYMBOL_NAME(sys_setresgid16)      /* 170 */
        .long SYMBOL_NAME(sys_getresgid16)
        .long SYMBOL_NAME(sys_prctl)
index 1248547..3ff7785 100644 (file)
@@ -162,7 +162,6 @@ config IA64_GENERIC
        select ACPI_NUMA
        select SWIOTLB
        select PCI_MSI
-       select DMAR
        help
          This selects the system type of your hardware.  A "generic" kernel
          will run on any supported IA-64 system.  However, if you configure
index 1d7bca0..0e5cd14 100644 (file)
@@ -234,3 +234,4 @@ CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_T10DIF=y
 CONFIG_MISC_DEVICES=y
+CONFIG_DMAR=y
index 97dd2ab..198c753 100644 (file)
@@ -1614,7 +1614,7 @@ sys_call_table:
        data8 sys_sched_get_priority_min
        data8 sys_sched_rr_get_interval
        data8 sys_nanosleep
-       data8 sys_nfsservctl
+       data8 sys_ni_syscall                    // old nfsservctl
        data8 sys_prctl                         // 1170
        data8 sys_getpagesize
        data8 sys_mmap2
index 528f2e6..f365c19 100644 (file)
@@ -168,7 +168,7 @@ ENTRY(sys_call_table)
        .long sys_tas                   /* vm86 syscall holder */
        .long sys_ni_syscall            /* query_module syscall holder */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall            /* was nfsservctl */
        .long sys_setresgid             /* 170 */
        .long sys_getresgid
        .long sys_prctl
index 31d5570..89f2014 100644 (file)
@@ -162,7 +162,7 @@ static inline __attribute_const__ int __virt_to_node_shift(void)
        pgdat->node_mem_map + (__pfn - pgdat->node_start_pfn);          \
 })
 #define page_to_pfn(_page) ({                                          \
-       struct page *__p = (_page);                                     \
+       const struct page *__p = (_page);                               \
        struct pglist_data *pgdat;                                      \
        pgdat = &pg_data_map[page_to_nid(__p)];                         \
        ((__p) - pgdat->node_mem_map) + pgdat->node_start_pfn;          \
index 00d1452..c468f2e 100644 (file)
@@ -189,7 +189,7 @@ ENTRY(sys_call_table)
        .long sys_getpagesize
        .long sys_ni_syscall            /* old "query_module" */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall            /* old nfsservctl */
        .long sys_setresgid16           /* 170 */
        .long sys_getresgid16
        .long sys_prctl
index d915a12..8789daa 100644 (file)
@@ -173,7 +173,7 @@ ENTRY(sys_call_table)
        .long sys_ni_syscall            /* sys_vm86 */
        .long sys_ni_syscall            /* Old sys_query_module */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall            /* old nfsservctl */
        .long sys_setresgid             /* 170 */
        .long sys_getresgid
        .long sys_prctl
index e521420..865bc7a 100644 (file)
@@ -424,7 +424,7 @@ einval:     li      v0, -ENOSYS
        sys     sys_getresuid           3
        sys     sys_ni_syscall          0       /* was sys_query_module */
        sys     sys_poll                3
-       sys     sys_nfsservctl          3
+       sys     sys_ni_syscall          0       /* was nfsservctl */
        sys     sys_setresgid           3       /* 4190 */
        sys     sys_getresgid           3
        sys     sys_prctl               5
index 85874d6..fb7334b 100644 (file)
@@ -299,7 +299,7 @@ sys_call_table:
        PTR     sys_ni_syscall                  /* 5170, was get_kernel_syms */
        PTR     sys_ni_syscall                  /* was query_module */
        PTR     sys_quotactl
-       PTR     sys_nfsservctl
+       PTR     sys_ni_syscall                  /* was nfsservctl */
        PTR     sys_ni_syscall                  /* res. for getpmsg */
        PTR     sys_ni_syscall                  /* 5175  for putpmsg */
        PTR     sys_ni_syscall                  /* res. for afs_syscall */
index b85842f..f9296e8 100644 (file)
@@ -294,7 +294,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_ni_syscall                  /* 6170, was get_kernel_syms */
        PTR     sys_ni_syscall                  /* was query_module */
        PTR     sys_quotactl
-       PTR     compat_sys_nfsservctl
+       PTR     sys_ni_syscall                  /* was nfsservctl */
        PTR     sys_ni_syscall                  /* res. for getpmsg */
        PTR     sys_ni_syscall                  /* 6175  for putpmsg */
        PTR     sys_ni_syscall                  /* res. for afs_syscall */
index 46c4763..4d7c982 100644 (file)
@@ -392,7 +392,7 @@ sys_call_table:
        PTR     sys_getresuid
        PTR     sys_ni_syscall                  /* was query_module */
        PTR     sys_poll
-       PTR     compat_sys_nfsservctl
+       PTR     sys_ni_syscall                  /* was nfsservctl */
        PTR     sys_setresgid                   /* 4190 */
        PTR     sys_getresgid
        PTR     sys_prctl
index ae435e1..3e3620d 100644 (file)
@@ -589,7 +589,7 @@ ENTRY(sys_call_table)
        .long sys_ni_syscall    /* vm86 */
        .long sys_ni_syscall    /* Old sys_query_module */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall    /* was nfsservctl */
        .long sys_setresgid16   /* 170 */
        .long sys_getresgid16
        .long sys_prctl
index 052f877..60b4722 100644 (file)
@@ -31,7 +31,6 @@
 
 #define DMA_ERROR_CODE         (~(dma_addr_t)0x0)
 
-int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
 
 #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)
@@ -47,6 +46,12 @@ dma_addr_t or1k_map_page(struct device *dev, struct page *page,
 void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
                     size_t size, enum dma_data_direction dir,
                     struct dma_attrs *attrs);
+int or1k_map_sg(struct device *dev, struct scatterlist *sg,
+               int nents, enum dma_data_direction dir,
+               struct dma_attrs *attrs);
+void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
+                  int nents, enum dma_data_direction dir,
+                  struct dma_attrs *attrs);
 void or1k_sync_single_for_cpu(struct device *dev,
                              dma_addr_t dma_handle, size_t size,
                              enum dma_data_direction dir);
@@ -98,6 +103,51 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
        debug_dma_unmap_page(dev, addr, size, dir, true);
 }
 
+static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
+                                  int nents, enum dma_data_direction dir)
+{
+       int i, ents;
+       struct scatterlist *s;
+
+       for_each_sg(sg, s, nents, i)
+               kmemcheck_mark_initialized(sg_virt(s), s->length);
+       BUG_ON(!valid_dma_direction(dir));
+       ents = or1k_map_sg(dev, sg, nents, dir, NULL);
+       debug_dma_map_sg(dev, sg, nents, ents, dir);
+
+       return ents;
+}
+
+static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+                                     int nents, enum dma_data_direction dir)
+{
+       BUG_ON(!valid_dma_direction(dir));
+       debug_dma_unmap_sg(dev, sg, nents, dir);
+       or1k_unmap_sg(dev, sg, nents, dir, NULL);
+}
+
+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
+                                     size_t offset, size_t size,
+                                     enum dma_data_direction dir)
+{
+       dma_addr_t addr;
+
+       kmemcheck_mark_initialized(page_address(page) + offset, size);
+       BUG_ON(!valid_dma_direction(dir));
+       addr = or1k_map_page(dev, page, offset, size, dir, NULL);
+       debug_dma_map_page(dev, page, offset, size, dir, addr, false);
+
+       return addr;
+}
+
+static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
+                                 size_t size, enum dma_data_direction dir)
+{
+       BUG_ON(!valid_dma_direction(dir));
+       or1k_unmap_page(dev, addr, size, dir, NULL);
+       debug_dma_unmap_page(dev, addr, size, dir, true);
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
                                           size_t size,
                                           enum dma_data_direction dir)
@@ -119,7 +169,12 @@ static inline void dma_sync_single_for_device(struct device *dev,
 static inline int dma_supported(struct device *dev, u64 dma_mask)
 {
        /* Support 32 bit DMA mask exclusively */
-       return dma_mask == 0xffffffffULL;
+       return dma_mask == DMA_BIT_MASK(32);
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+       return 0;
 }
 
 static inline int dma_set_mask(struct device *dev, u64 dma_mask)
index 54a5c50..b79c2b1 100644 (file)
 
 /* This struct is saved by setup_frame in signal.c, to keep the current
    context while a signal handler is executed. It's restored by sys_sigreturn.
-
-   To keep things simple, we use pt_regs here even though normally you just
-   specify the list of regs to save. Then we can use copy_from_user on the
-   entire regs instead of a bunch of get_user's as well...
 */
 
 struct sigcontext {
-       struct pt_regs regs;  /* needs to be first */
+       struct user_regs_struct regs;  /* needs to be first */
        unsigned long oldmask;
-       unsigned long usp;    /* usp before stacking this gunk on it */
 };
 
 #endif /* __ASM_OPENRISC_SIGCONTEXT_H */
index 968d3ee..f1c8ee2 100644 (file)
@@ -154,6 +154,33 @@ void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
        /* Nothing special to do here... */
 }
 
+int or1k_map_sg(struct device *dev, struct scatterlist *sg,
+               int nents, enum dma_data_direction dir,
+               struct dma_attrs *attrs)
+{
+       struct scatterlist *s;
+       int i;
+
+       for_each_sg(sg, s, nents, i) {
+               s->dma_address = or1k_map_page(dev, sg_page(s), s->offset,
+                                              s->length, dir, NULL);
+       }
+
+       return nents;
+}
+
+void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
+                  int nents, enum dma_data_direction dir,
+                  struct dma_attrs *attrs)
+{
+       struct scatterlist *s;
+       int i;
+
+       for_each_sg(sg, s, nents, i) {
+               or1k_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, NULL);
+       }
+}
+
 void or1k_sync_single_for_cpu(struct device *dev,
                              dma_addr_t dma_handle, size_t size,
                              enum dma_data_direction dir)
@@ -187,5 +214,4 @@ static int __init dma_init(void)
 
        return 0;
 }
-
 fs_initcall(dma_init);
index 5f759c7..95207ab 100644 (file)
@@ -52,31 +52,25 @@ struct rt_sigframe {
 static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 {
        unsigned int err = 0;
-       unsigned long old_usp;
 
        /* Alwys make any pending restarted system call return -EINTR */
        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
-       /* restore the regs from &sc->regs (same as sc, since regs is first)
+       /*
+        * Restore the regs from &sc->regs.
         * (sc is already checked for VERIFY_READ since the sigframe was
         *  checked in sys_sigreturn previously)
         */
-
-       if (__copy_from_user(regs, sc, sizeof(struct pt_regs)))
+       if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)))
+               goto badframe;
+       if (__copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long)))
+               goto badframe;
+       if (__copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long)))
                goto badframe;
 
        /* make sure the SM-bit is cleared so user-mode cannot fool us */
        regs->sr &= ~SPR_SR_SM;
 
-       /* restore the old USP as it was before we stacked the sc etc.
-        * (we cannot just pop the sigcontext since we aligned the sp and
-        *  stuff after pushing it)
-        */
-
-       err |= __get_user(old_usp, &sc->usp);
-
-       regs->sp = old_usp;
-
        /* TODO: the other ports use regs->orig_XX to disable syscall checks
         * after this completes, but we don't use that mechanism. maybe we can
         * use it now ?
@@ -137,18 +131,17 @@ static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
                            unsigned long mask)
 {
        int err = 0;
-       unsigned long usp = regs->sp;
 
-       /* copy the regs. they are first in sc so we can use sc directly */
+       /* copy the regs */
 
-       err |= __copy_to_user(sc, regs, sizeof(struct pt_regs));
+       err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
+       err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
+       err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
 
        /* then some other stuff */
 
        err |= __put_user(mask, &sc->oldmask);
 
-       err |= __put_user(usp, &sc->usp);
-
        return err;
 }
 
index e66366f..3735abd 100644 (file)
        ENTRY_SAME(ni_syscall)          /* query_module */
        ENTRY_SAME(poll)
        /* structs contain pointers and an in_addr... */
-       ENTRY_COMP(nfsservctl)
+       ENTRY_SAME(ni_syscall)          /* was nfsservctl */
        ENTRY_SAME(setresgid)           /* 170 */
        ENTRY_SAME(getresgid)
        ENTRY_SAME(prctl)
index bfa96aa..d9b7767 100644 (file)
                        #size-cells = <1>;
                        compatible = "cfi-flash";
                        reg = <0x0 0x0 0x02000000>;
-                       bank-width = <1>;
+                       bank-width = <2>;
                        device-width = <1>;
                        partition@0 {
                                label = "ramdisk";
index 980ff8f..3ff5a81 100644 (file)
@@ -171,3 +171,4 @@ CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_AES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
index 10562a5..4311d02 100644 (file)
@@ -185,3 +185,4 @@ CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_AES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
index d322835..c92c204 100644 (file)
@@ -100,5 +100,8 @@ CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_AES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DEV_TALITOS=y
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
index fcd85d2..a3467bf 100644 (file)
@@ -139,6 +139,7 @@ CONFIG_SND=y
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_PPC is not set
 # CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
index 908c941..9693f6e 100644 (file)
@@ -140,6 +140,7 @@ CONFIG_SND=y
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_PPC is not set
 # CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
index f6736b7..fa0d27a 100644 (file)
@@ -171,7 +171,7 @@ SYSCALL_SPU(setresuid)
 SYSCALL_SPU(getresuid)
 SYSCALL(ni_syscall)
 SYSCALL_SPU(poll)
-COMPAT_SYS(nfsservctl)
+SYSCALL(ni_syscall)
 SYSCALL_SPU(setresgid)
 SYSCALL_SPU(getresgid)
 COMPAT_SYS_SPU(prctl)
index 2de8551..c65f75a 100644 (file)
@@ -54,6 +54,7 @@
 #define ODSR_CLEAR             0x1c00
 #define LTLEECSR_ENABLE_ALL    0xFFC000FC
 #define ESCSR_CLEAR            0x07120204
+#define IECSR_CLEAR            0x80000000
 
 #define RIO_PORT1_EDCSR                0x0640
 #define RIO_PORT2_EDCSR                0x0680
@@ -1089,11 +1090,11 @@ static void port_error_handler(struct rio_mport *port, int offset)
 
        if (offset == 0) {
                out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0);
-               out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), 0);
+               out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), IECSR_CLEAR);
                out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR);
        } else {
                out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0);
-               out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), 0);
+               out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), IECSR_CLEAR);
                out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR);
        }
 }
index 08ab9aa..7526db6 100644 (file)
@@ -665,12 +665,6 @@ ENTRY(sys32_poll_wrapper)
        lgfr    %r4,%r4                 # long
        jg      sys_poll                # branch to system call
 
-ENTRY(compat_sys_nfsservctl_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # struct compat_nfsctl_arg*
-       llgtr   %r4,%r4                 # union compat_nfsctl_res*
-       jg      compat_sys_nfsservctl   # branch to system call
-
 ENTRY(sys32_setresgid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
        llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t
index 068f846..f297456 100644 (file)
@@ -396,17 +396,19 @@ static __init void detect_machine_facilities(void)
 static __init void rescue_initrd(void)
 {
 #ifdef CONFIG_BLK_DEV_INITRD
+       unsigned long min_initrd_addr = (unsigned long) _end + (4UL << 20);
        /*
-        * Move the initrd right behind the bss section in case it starts
-        * within the bss section. So we don't overwrite it when the bss
-        * section gets cleared.
+        * Just like in case of IPL from VM reader we make sure there is a
+        * gap of 4MB between end of kernel and start of initrd.
+        * That way we can also be sure that saving an NSS will succeed,
+        * which however only requires different segments.
         */
        if (!INITRD_START || !INITRD_SIZE)
                return;
-       if (INITRD_START >= (unsigned long) __bss_stop)
+       if (INITRD_START >= min_initrd_addr)
                return;
-       memmove(__bss_stop, (void *) INITRD_START, INITRD_SIZE);
-       INITRD_START = (unsigned long) __bss_stop;
+       memmove((void *) min_initrd_addr, (void *) INITRD_START, INITRD_SIZE);
+       INITRD_START = min_initrd_addr;
 #endif
 }
 
index 04361d5..48c7102 100644 (file)
@@ -1220,7 +1220,7 @@ static int __init reipl_fcp_init(void)
        /* sysfs: create fcp kset for mixing attr group and bin attrs */
        reipl_fcp_kset = kset_create_and_add(IPL_FCP_STR, NULL,
                                             &reipl_kset->kobj);
-       if (!reipl_kset) {
+       if (!reipl_fcp_kset) {
                free_page((unsigned long) reipl_block_fcp);
                return -ENOMEM;
        }
@@ -1618,7 +1618,8 @@ static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
 
 static void stop_run(struct shutdown_trigger *trigger)
 {
-       if (strcmp(trigger->name, ON_PANIC_STR) == 0)
+       if (strcmp(trigger->name, ON_PANIC_STR) == 0 ||
+           strcmp(trigger->name, ON_RESTART_STR) == 0)
                disabled_wait((unsigned long) __builtin_return_address(0));
        while (sigp(smp_processor_id(), sigp_stop) == sigp_busy)
                cpu_relax();
@@ -1717,7 +1718,7 @@ static void do_panic(void)
 /* on restart */
 
 static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR,
-       &reipl_action};
+       &stop_action};
 
 static ssize_t on_restart_show(struct kobject *kobj,
                               struct kobj_attribute *attr, char *page)
index 6ee39ef..73eb08c 100644 (file)
@@ -177,7 +177,7 @@ SYSCALL(sys_getresuid16,sys_ni_syscall,sys32_getresuid16_wrapper)   /* 165 old get
 NI_SYSCALL                                                     /* for vm86 */
 NI_SYSCALL                                                     /* old sys_query_module */
 SYSCALL(sys_poll,sys_poll,sys32_poll_wrapper)
-SYSCALL(sys_nfsservctl,sys_nfsservctl,compat_sys_nfsservctl_wrapper)
+NI_SYSCALL                                                     /* old nfsservctl */
 SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper)      /* 170 old setresgid16 syscall */
 SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper)      /* old getresgid16 syscall */
 SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper)
index b97baf8..2d3679b 100644 (file)
@@ -123,7 +123,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
 struct perf_event;
 struct perf_sample_data;
 
-extern void ptrace_triggered(struct perf_event *bp, int nmi,
+extern void ptrace_triggered(struct perf_event *bp,
                      struct perf_sample_data *data, struct pt_regs *regs);
 
 #define task_pt_regs(task) \
index e915dea..0555929 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/serial_sci.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
 #include <linux/sh_timer.h>
 #include <linux/sh_dma.h>
 
index 32114e0..db4ecd7 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/atomic.h>
 #include <asm/smp.h>
 
-static void (*pm_idle)(void);
+void (*pm_idle)(void);
 
 static int hlt_counter;
 
index 39b051d..293e39c 100644 (file)
@@ -185,7 +185,7 @@ ENTRY(sys_call_table)
        .long sys_ni_syscall    /* vm86 */
        .long sys_ni_syscall    /* old "query_module" */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall    /* was nfsservctl */
        .long sys_setresgid16   /* 170 */
        .long sys_getresgid16
        .long sys_prctl
index 089c4d8..ceb34b9 100644 (file)
@@ -189,7 +189,7 @@ sys_call_table:
        .long sys_ni_syscall    /* vm86 */
        .long sys_ni_syscall    /* old "query_module" */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall    /* was nfsservctl */
        .long sys_setresgid16           /* 170 */
        .long sys_getresgid16
        .long sys_prctl
index d9006f8..7bbef95 100644 (file)
@@ -316,6 +316,35 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
                        break;
                }
                break;
+
+       case 9: /* mov.w @(disp,PC),Rn */
+               srcu = (unsigned char __user *)regs->pc;
+               srcu += 4;
+               srcu += (instruction & 0x00FF) << 1;
+               dst = (unsigned char *)rn;
+               *(unsigned long *)dst = 0;
+
+#if !defined(__LITTLE_ENDIAN__)
+               dst += 2;
+#endif
+
+               if (ma->from(dst, srcu, 2))
+                       goto fetch_fault;
+               sign_extend(2, dst);
+               ret = 0;
+               break;
+
+       case 0xd: /* mov.l @(disp,PC),Rn */
+               srcu = (unsigned char __user *)(regs->pc & ~0x3);
+               srcu += 4;
+               srcu += (instruction & 0x00FF) << 2;
+               dst = (unsigned char *)rn;
+               *(unsigned long *)dst = 0;
+
+               if (ma->from(dst, srcu, 4))
+                       goto fetch_fault;
+               ret = 0;
+               break;
        }
        return ret;
 
@@ -466,6 +495,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
                case 0x0500: /* mov.w @(disp,Rm),R0 */
                        goto simple;
                case 0x0B00: /* bf   lab - no delayslot*/
+                       ret = 0;
                        break;
                case 0x0F00: /* bf/s lab */
                        ret = handle_delayslot(regs, instruction, ma);
@@ -479,6 +509,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
                        }
                        break;
                case 0x0900: /* bt   lab - no delayslot */
+                       ret = 0;
                        break;
                case 0x0D00: /* bt/s lab */
                        ret = handle_delayslot(regs, instruction, ma);
@@ -494,6 +525,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
                }
                break;
 
+       case 0x9000: /* mov.w @(disp,Rm),Rn */
+               goto simple;
+
        case 0xA000: /* bra label */
                ret = handle_delayslot(regs, instruction, ma);
                if (ret==0)
@@ -507,6 +541,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
                        regs->pc += SH_PC_12BIT_OFFSET(instruction);
                }
                break;
+
+       case 0xD000: /* mov.l @(disp,Rm),Rn */
+               goto simple;
        }
        return ret;
 
index 42c67be..1a6f20d 100644 (file)
@@ -55,6 +55,7 @@ config SPARC64
        select PERF_USE_VMALLOC
        select IRQ_PREFLOW_FASTEOI
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
+       select HAVE_C_RECORDMCOUNT
 
 config ARCH_DEFCONFIG
        string
index a1607d1..69914d7 100644 (file)
@@ -45,6 +45,19 @@ typedef struct {
        int                     si_mask;
 } __siginfo32_t;
 
+#define __SIGC_MAXWIN  7
+
+typedef struct {
+       unsigned long locals[8];
+       unsigned long ins[8];
+} __siginfo_reg_window;
+
+typedef struct {
+       int                     wsaved;
+       __siginfo_reg_window    reg_window[__SIGC_MAXWIN];
+       unsigned long           rwbuf_stkptrs[__SIGC_MAXWIN];
+} __siginfo_rwin_t;
+
 #ifdef CONFIG_SPARC64
 typedef struct {
        unsigned   int si_float_regs [64];
@@ -73,6 +86,7 @@ struct sigcontext {
                unsigned long   ss_size;
        }                       sigc_stack;
        unsigned long           sigc_mask;
+       __siginfo_rwin_t *      sigc_rwin_save;
 };
 
 #else
index 5f5b8bf..bcc98fc 100644 (file)
@@ -131,6 +131,15 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
        *(volatile __u32 *)&lp->lock = ~0U;
 }
 
+static void inline arch_write_unlock(arch_rwlock_t *lock)
+{
+       __asm__ __volatile__(
+"      st              %%g0, [%0]"
+       : /* no outputs */
+       : "r" (lock)
+       : "memory");
+}
+
 static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
        unsigned int val;
@@ -175,8 +184,6 @@ static inline int __arch_read_trylock(arch_rwlock_t *rw)
        res; \
 })
 
-#define arch_write_unlock(rw)  do { (rw)->lock = 0; } while(0)
-
 #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
 #define arch_read_lock_flags(rw, flags)   arch_read_lock(rw)
 #define arch_write_lock_flags(rw, flags)  arch_write_lock(rw)
index 073936a..9689176 100644 (file)
@@ -210,14 +210,8 @@ static int inline arch_write_trylock(arch_rwlock_t *lock)
        return result;
 }
 
-#define arch_read_lock(p)      arch_read_lock(p)
 #define arch_read_lock_flags(p, f) arch_read_lock(p)
-#define arch_read_trylock(p)   arch_read_trylock(p)
-#define arch_read_unlock(p)    arch_read_unlock(p)
-#define arch_write_lock(p)     arch_write_lock(p)
 #define arch_write_lock_flags(p, f) arch_write_lock(p)
-#define arch_write_unlock(p)   arch_write_unlock(p)
-#define arch_write_trylock(p)  arch_write_trylock(p)
 
 #define arch_read_can_lock(rw)         (!((rw)->lock & 0x80000000UL))
 #define arch_write_can_lock(rw)        (!(rw)->lock)
index b90b4a1..cb85458 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_SPARC32)   += sun4m_irq.o sun4c_irq.o sun4d_irq.o
 
 obj-y                   += process_$(BITS).o
 obj-y                   += signal_$(BITS).o
+obj-y                   += sigutil_$(BITS).o
 obj-$(CONFIG_SPARC32)   += ioport.o
 obj-y                   += setup_$(BITS).o
 obj-y                   += idprom.o
index 100b9c2..4285112 100644 (file)
@@ -88,7 +88,7 @@ BTFIXUPDEF_CALL(void, set_irq_udt, int)
 #define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu)
 
 /* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */
-#define SUN4D_IPI_IRQ 14
+#define SUN4D_IPI_IRQ 13
 
 extern void sun4d_ipi_interrupt(void);
 
index a19f041..1aaf8c1 100644 (file)
@@ -352,8 +352,8 @@ int __init pcic_probe(void)
        strcpy(pbm->prom_name, namebuf);
 
        {
-               extern volatile int t_nmi[1];
-               extern int pcic_nmi_trap_patch[1];
+               extern volatile int t_nmi[4];
+               extern int pcic_nmi_trap_patch[4];
 
                t_nmi[0] = pcic_nmi_trap_patch[0];
                t_nmi[1] = pcic_nmi_trap_patch[1];
index 3e9daea..3c5bb78 100644 (file)
@@ -440,8 +440,14 @@ static void __init init_sparc64_elf_hwcap(void)
                        cap |= AV_SPARC_VIS;
                if (tlb_type == cheetah || tlb_type == cheetah_plus)
                        cap |= AV_SPARC_VIS | AV_SPARC_VIS2;
-               if (tlb_type == cheetah_plus)
-                       cap |= AV_SPARC_POPC;
+               if (tlb_type == cheetah_plus) {
+                       unsigned long impl, ver;
+
+                       __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
+                       impl = ((ver >> 32) & 0xffff);
+                       if (impl == PANTHER_IMPL)
+                               cap |= AV_SPARC_POPC;
+               }
                if (tlb_type == hypervisor) {
                        if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1)
                                cap |= AV_SPARC_ASI_BLK_INIT;
index 75fad42..1ba95af 100644 (file)
@@ -29,6 +29,8 @@
 #include <asm/visasm.h>
 #include <asm/compat_signal.h>
 
+#include "sigutil.h"
+
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 /* This magic should be in g_upper[0] for all upper parts
@@ -44,14 +46,14 @@ typedef struct {
 struct signal_frame32 {
        struct sparc_stackf32   ss;
        __siginfo32_t           info;
-       /* __siginfo_fpu32_t * */ u32 fpu_save;
+       /* __siginfo_fpu_t * */ u32 fpu_save;
        unsigned int            insns[2];
        unsigned int            extramask[_COMPAT_NSIG_WORDS - 1];
        unsigned int            extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
        /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
        siginfo_extra_v8plus_t  v8plus;
-       __siginfo_fpu_t         fpu_state;
-};
+       /* __siginfo_rwin_t * */u32 rwin_save;
+} __attribute__((aligned(8)));
 
 typedef struct compat_siginfo{
        int si_signo;
@@ -110,18 +112,14 @@ struct rt_signal_frame32 {
        compat_siginfo_t        info;
        struct pt_regs32        regs;
        compat_sigset_t         mask;
-       /* __siginfo_fpu32_t * */ u32 fpu_save;
+       /* __siginfo_fpu_t * */ u32 fpu_save;
        unsigned int            insns[2];
        stack_t32               stack;
        unsigned int            extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
        /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
        siginfo_extra_v8plus_t  v8plus;
-       __siginfo_fpu_t         fpu_state;
-};
-
-/* Align macros */
-#define SF_ALIGNEDSZ  (((sizeof(struct signal_frame32) + 15) & (~15)))
-#define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame32) + 15) & (~15)))
+       /* __siginfo_rwin_t * */u32 rwin_save;
+} __attribute__((aligned(8)));
 
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
@@ -192,30 +190,13 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
        return 0;
 }
 
-static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
-{
-       unsigned long *fpregs = current_thread_info()->fpregs;
-       unsigned long fprs;
-       int err;
-       
-       err = __get_user(fprs, &fpu->si_fprs);
-       fprs_write(0);
-       regs->tstate &= ~TSTATE_PEF;
-       if (fprs & FPRS_DL)
-               err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32));
-       if (fprs & FPRS_DU)
-               err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32));
-       err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
-       err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
-       current_thread_info()->fpsaved[0] |= fprs;
-       return err;
-}
-
 void do_sigreturn32(struct pt_regs *regs)
 {
        struct signal_frame32 __user *sf;
+       compat_uptr_t fpu_save;
+       compat_uptr_t rwin_save;
        unsigned int psr;
-       unsigned pc, npc, fpu_save;
+       unsigned pc, npc;
        sigset_t set;
        unsigned seta[_COMPAT_NSIG_WORDS];
        int err, i;
@@ -273,8 +254,13 @@ void do_sigreturn32(struct pt_regs *regs)
        pt_regs_clear_syscall(regs);
 
        err |= __get_user(fpu_save, &sf->fpu_save);
-       if (fpu_save)
-               err |= restore_fpu_state32(regs, &sf->fpu_state);
+       if (!err && fpu_save)
+               err |= restore_fpu_state(regs, compat_ptr(fpu_save));
+       err |= __get_user(rwin_save, &sf->rwin_save);
+       if (!err && rwin_save) {
+               if (restore_rwin_state(compat_ptr(rwin_save)))
+                       goto segv;
+       }
        err |= __get_user(seta[0], &sf->info.si_mask);
        err |= copy_from_user(seta+1, &sf->extramask,
                              (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
@@ -300,7 +286,9 @@ segv:
 asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
 {
        struct rt_signal_frame32 __user *sf;
-       unsigned int psr, pc, npc, fpu_save, u_ss_sp;
+       unsigned int psr, pc, npc, u_ss_sp;
+       compat_uptr_t fpu_save;
+       compat_uptr_t rwin_save;
        mm_segment_t old_fs;
        sigset_t set;
        compat_sigset_t seta;
@@ -359,8 +347,8 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
        pt_regs_clear_syscall(regs);
 
        err |= __get_user(fpu_save, &sf->fpu_save);
-       if (fpu_save)
-               err |= restore_fpu_state32(regs, &sf->fpu_state);
+       if (!err && fpu_save)
+               err |= restore_fpu_state(regs, compat_ptr(fpu_save));
        err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t));
        err |= __get_user(u_ss_sp, &sf->stack.ss_sp);
        st.ss_sp = compat_ptr(u_ss_sp);
@@ -376,6 +364,12 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
        do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf);
        set_fs(old_fs);
        
+       err |= __get_user(rwin_save, &sf->rwin_save);
+       if (!err && rwin_save) {
+               if (restore_rwin_state(compat_ptr(rwin_save)))
+                       goto segv;
+       }
+
        switch (_NSIG_WORDS) {
                case 4: set.sig[3] = seta.sig[6] + (((long)seta.sig[7]) << 32);
                case 3: set.sig[2] = seta.sig[4] + (((long)seta.sig[5]) << 32);
@@ -433,26 +427,6 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
        return (void __user *) sp;
 }
 
-static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
-{
-       unsigned long *fpregs = current_thread_info()->fpregs;
-       unsigned long fprs;
-       int err = 0;
-       
-       fprs = current_thread_info()->fpsaved[0];
-       if (fprs & FPRS_DL)
-               err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
-                                   (sizeof(unsigned int) * 32));
-       if (fprs & FPRS_DU)
-               err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
-                                   (sizeof(unsigned int) * 32));
-       err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
-       err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
-       err |= __put_user(fprs, &fpu->si_fprs);
-
-       return err;
-}
-
 /* The I-cache flush instruction only works in the primary ASI, which
  * right now is the nucleus, aka. kernel space.
  *
@@ -515,18 +489,23 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
                         int signo, sigset_t *oldset)
 {
        struct signal_frame32 __user *sf;
+       int i, err, wsaved;
+       void __user *tail;
        int sigframe_size;
        u32 psr;
-       int i, err;
        unsigned int seta[_COMPAT_NSIG_WORDS];
 
        /* 1. Make sure everything is clean */
        synchronize_user_stack();
        save_and_clear_fpu();
        
-       sigframe_size = SF_ALIGNEDSZ;
-       if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
-               sigframe_size -= sizeof(__siginfo_fpu_t);
+       wsaved = get_thread_wsaved();
+
+       sigframe_size = sizeof(*sf);
+       if (current_thread_info()->fpsaved[0] & FPRS_FEF)
+               sigframe_size += sizeof(__siginfo_fpu_t);
+       if (wsaved)
+               sigframe_size += sizeof(__siginfo_rwin_t);
 
        sf = (struct signal_frame32 __user *)
                get_sigframe(&ka->sa, regs, sigframe_size);
@@ -534,8 +513,7 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
        if (invalid_frame_pointer(sf, sigframe_size))
                goto sigill;
 
-       if (get_thread_wsaved() != 0)
-               goto sigill;
+       tail = (sf + 1);
 
        /* 2. Save the current process state */
        if (test_thread_flag(TIF_32BIT)) {
@@ -560,11 +538,22 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
                          &sf->v8plus.asi);
 
        if (psr & PSR_EF) {
-               err |= save_fpu_state32(regs, &sf->fpu_state);
-               err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
+               __siginfo_fpu_t __user *fp = tail;
+               tail += sizeof(*fp);
+               err |= save_fpu_state(regs, fp);
+               err |= __put_user((u64)fp, &sf->fpu_save);
        } else {
                err |= __put_user(0, &sf->fpu_save);
        }
+       if (wsaved) {
+               __siginfo_rwin_t __user *rwp = tail;
+               tail += sizeof(*rwp);
+               err |= save_rwin_state(wsaved, rwp);
+               err |= __put_user((u64)rwp, &sf->rwin_save);
+               set_thread_wsaved(0);
+       } else {
+               err |= __put_user(0, &sf->rwin_save);
+       }
 
        switch (_NSIG_WORDS) {
        case 4: seta[7] = (oldset->sig[3] >> 32);
@@ -580,10 +569,21 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
        err |= __copy_to_user(sf->extramask, seta + 1,
                              (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
 
-       err |= copy_in_user((u32 __user *)sf,
-                           (u32 __user *)(regs->u_regs[UREG_FP]),
-                           sizeof(struct reg_window32));
-       
+       if (!wsaved) {
+               err |= copy_in_user((u32 __user *)sf,
+                                   (u32 __user *)(regs->u_regs[UREG_FP]),
+                                   sizeof(struct reg_window32));
+       } else {
+               struct reg_window *rp;
+
+               rp = &current_thread_info()->reg_window[wsaved - 1];
+               for (i = 0; i < 8; i++)
+                       err |= __put_user(rp->locals[i], &sf->ss.locals[i]);
+               for (i = 0; i < 6; i++)
+                       err |= __put_user(rp->ins[i], &sf->ss.ins[i]);
+               err |= __put_user(rp->ins[6], &sf->ss.fp);
+               err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
+       }       
        if (err)
                goto sigsegv;
 
@@ -613,7 +613,6 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
                err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
                if (err)
                        goto sigsegv;
-
                flush_signal_insns(address);
        }
        return 0;
@@ -632,18 +631,23 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
                            siginfo_t *info)
 {
        struct rt_signal_frame32 __user *sf;
+       int i, err, wsaved;
+       void __user *tail;
        int sigframe_size;
        u32 psr;
-       int i, err;
        compat_sigset_t seta;
 
        /* 1. Make sure everything is clean */
        synchronize_user_stack();
        save_and_clear_fpu();
        
-       sigframe_size = RT_ALIGNEDSZ;
-       if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
-               sigframe_size -= sizeof(__siginfo_fpu_t);
+       wsaved = get_thread_wsaved();
+
+       sigframe_size = sizeof(*sf);
+       if (current_thread_info()->fpsaved[0] & FPRS_FEF)
+               sigframe_size += sizeof(__siginfo_fpu_t);
+       if (wsaved)
+               sigframe_size += sizeof(__siginfo_rwin_t);
 
        sf = (struct rt_signal_frame32 __user *)
                get_sigframe(&ka->sa, regs, sigframe_size);
@@ -651,8 +655,7 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
        if (invalid_frame_pointer(sf, sigframe_size))
                goto sigill;
 
-       if (get_thread_wsaved() != 0)
-               goto sigill;
+       tail = (sf + 1);
 
        /* 2. Save the current process state */
        if (test_thread_flag(TIF_32BIT)) {
@@ -677,11 +680,22 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
                          &sf->v8plus.asi);
 
        if (psr & PSR_EF) {
-               err |= save_fpu_state32(regs, &sf->fpu_state);
-               err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
+               __siginfo_fpu_t __user *fp = tail;
+               tail += sizeof(*fp);
+               err |= save_fpu_state(regs, fp);
+               err |= __put_user((u64)fp, &sf->fpu_save);
        } else {
                err |= __put_user(0, &sf->fpu_save);
        }
+       if (wsaved) {
+               __siginfo_rwin_t __user *rwp = tail;
+               tail += sizeof(*rwp);
+               err |= save_rwin_state(wsaved, rwp);
+               err |= __put_user((u64)rwp, &sf->rwin_save);
+               set_thread_wsaved(0);
+       } else {
+               err |= __put_user(0, &sf->rwin_save);
+       }
 
        /* Update the siginfo structure.  */
        err |= copy_siginfo_to_user32(&sf->info, info);
@@ -703,9 +717,21 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
        }
        err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t));
 
-       err |= copy_in_user((u32 __user *)sf,
-                           (u32 __user *)(regs->u_regs[UREG_FP]),
-                           sizeof(struct reg_window32));
+       if (!wsaved) {
+               err |= copy_in_user((u32 __user *)sf,
+                                   (u32 __user *)(regs->u_regs[UREG_FP]),
+                                   sizeof(struct reg_window32));
+       } else {
+               struct reg_window *rp;
+
+               rp = &current_thread_info()->reg_window[wsaved - 1];
+               for (i = 0; i < 8; i++)
+                       err |= __put_user(rp->locals[i], &sf->ss.locals[i]);
+               for (i = 0; i < 6; i++)
+                       err |= __put_user(rp->ins[i], &sf->ss.ins[i]);
+               err |= __put_user(rp->ins[6], &sf->ss.fp);
+               err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
+       }
        if (err)
                goto sigsegv;
        
index 5e5c5fd..04ede8f 100644 (file)
@@ -26,6 +26,8 @@
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>    /* flush_sig_insns */
 
+#include "sigutil.h"
+
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
@@ -39,8 +41,8 @@ struct signal_frame {
        unsigned long           insns[2] __attribute__ ((aligned (8)));
        unsigned int            extramask[_NSIG_WORDS - 1];
        unsigned int            extra_size; /* Should be 0 */
-       __siginfo_fpu_t         fpu_state;
-};
+       __siginfo_rwin_t __user *rwin_save;
+} __attribute__((aligned(8)));
 
 struct rt_signal_frame {
        struct sparc_stackf     ss;
@@ -51,8 +53,8 @@ struct rt_signal_frame {
        unsigned int            insns[2];
        stack_t                 stack;
        unsigned int            extra_size; /* Should be 0 */
-       __siginfo_fpu_t         fpu_state;
-};
+       __siginfo_rwin_t __user *rwin_save;
+} __attribute__((aligned(8)));
 
 /* Align macros */
 #define SF_ALIGNEDSZ  (((sizeof(struct signal_frame) + 7) & (~7)))
@@ -79,43 +81,13 @@ asmlinkage int sys_sigsuspend(old_sigset_t set)
        return _sigpause_common(set);
 }
 
-static inline int
-restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
-{
-       int err;
-#ifdef CONFIG_SMP
-       if (test_tsk_thread_flag(current, TIF_USEDFPU))
-               regs->psr &= ~PSR_EF;
-#else
-       if (current == last_task_used_math) {
-               last_task_used_math = NULL;
-               regs->psr &= ~PSR_EF;
-       }
-#endif
-       set_used_math();
-       clear_tsk_thread_flag(current, TIF_USEDFPU);
-
-       if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu)))
-               return -EFAULT;
-
-       err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
-                              (sizeof(unsigned long) * 32));
-       err |= __get_user(current->thread.fsr, &fpu->si_fsr);
-       err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
-       if (current->thread.fpqdepth != 0)
-               err |= __copy_from_user(&current->thread.fpqueue[0],
-                                       &fpu->si_fpqueue[0],
-                                       ((sizeof(unsigned long) +
-                                       (sizeof(unsigned long *)))*16));
-       return err;
-}
-
 asmlinkage void do_sigreturn(struct pt_regs *regs)
 {
        struct signal_frame __user *sf;
        unsigned long up_psr, pc, npc;
        sigset_t set;
        __siginfo_fpu_t __user *fpu_save;
+       __siginfo_rwin_t __user *rwin_save;
        int err;
 
        /* Always make any pending restarted system calls return -EINTR */
@@ -150,9 +122,11 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
        pt_regs_clear_syscall(regs);
 
        err |= __get_user(fpu_save, &sf->fpu_save);
-
        if (fpu_save)
                err |= restore_fpu_state(regs, fpu_save);
+       err |= __get_user(rwin_save, &sf->rwin_save);
+       if (rwin_save)
+               err |= restore_rwin_state(rwin_save);
 
        /* This is pretty much atomic, no amount locking would prevent
         * the races which exist anyways.
@@ -180,6 +154,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
        struct rt_signal_frame __user *sf;
        unsigned int psr, pc, npc;
        __siginfo_fpu_t __user *fpu_save;
+       __siginfo_rwin_t __user *rwin_save;
        mm_segment_t old_fs;
        sigset_t set;
        stack_t st;
@@ -207,8 +182,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
        pt_regs_clear_syscall(regs);
 
        err |= __get_user(fpu_save, &sf->fpu_save);
-
-       if (fpu_save)
+       if (!err && fpu_save)
                err |= restore_fpu_state(regs, fpu_save);
        err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
        
@@ -228,6 +202,12 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
        do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf);
        set_fs(old_fs);
 
+       err |= __get_user(rwin_save, &sf->rwin_save);
+       if (!err && rwin_save) {
+               if (restore_rwin_state(rwin_save))
+                       goto segv;
+       }
+
        sigdelsetmask(&set, ~_BLOCKABLE);
        spin_lock_irq(&current->sighand->siglock);
        current->blocked = set;
@@ -280,53 +260,23 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
        return (void __user *) sp;
 }
 
-static inline int
-save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
-{
-       int err = 0;
-#ifdef CONFIG_SMP
-       if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
-               put_psr(get_psr() | PSR_EF);
-               fpsave(&current->thread.float_regs[0], &current->thread.fsr,
-                      &current->thread.fpqueue[0], &current->thread.fpqdepth);
-               regs->psr &= ~(PSR_EF);
-               clear_tsk_thread_flag(current, TIF_USEDFPU);
-       }
-#else
-       if (current == last_task_used_math) {
-               put_psr(get_psr() | PSR_EF);
-               fpsave(&current->thread.float_regs[0], &current->thread.fsr,
-                      &current->thread.fpqueue[0], &current->thread.fpqdepth);
-               last_task_used_math = NULL;
-               regs->psr &= ~(PSR_EF);
-       }
-#endif
-       err |= __copy_to_user(&fpu->si_float_regs[0],
-                             &current->thread.float_regs[0],
-                             (sizeof(unsigned long) * 32));
-       err |= __put_user(current->thread.fsr, &fpu->si_fsr);
-       err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
-       if (current->thread.fpqdepth != 0)
-               err |= __copy_to_user(&fpu->si_fpqueue[0],
-                                     &current->thread.fpqueue[0],
-                                     ((sizeof(unsigned long) +
-                                     (sizeof(unsigned long *)))*16));
-       clear_used_math();
-       return err;
-}
-
 static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
                       int signo, sigset_t *oldset)
 {
        struct signal_frame __user *sf;
-       int sigframe_size, err;
+       int sigframe_size, err, wsaved;
+       void __user *tail;
 
        /* 1. Make sure everything is clean */
        synchronize_user_stack();
 
-       sigframe_size = SF_ALIGNEDSZ;
-       if (!used_math())
-               sigframe_size -= sizeof(__siginfo_fpu_t);
+       wsaved = current_thread_info()->w_saved;
+
+       sigframe_size = sizeof(*sf);
+       if (used_math())
+               sigframe_size += sizeof(__siginfo_fpu_t);
+       if (wsaved)
+               sigframe_size += sizeof(__siginfo_rwin_t);
 
        sf = (struct signal_frame __user *)
                get_sigframe(&ka->sa, regs, sigframe_size);
@@ -334,8 +284,7 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
        if (invalid_frame_pointer(sf, sigframe_size))
                goto sigill_and_return;
 
-       if (current_thread_info()->w_saved != 0)
-               goto sigill_and_return;
+       tail = sf + 1;
 
        /* 2. Save the current process state */
        err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs));
@@ -343,17 +292,34 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
        err |= __put_user(0, &sf->extra_size);
 
        if (used_math()) {
-               err |= save_fpu_state(regs, &sf->fpu_state);
-               err |= __put_user(&sf->fpu_state, &sf->fpu_save);
+               __siginfo_fpu_t __user *fp = tail;
+               tail += sizeof(*fp);
+               err |= save_fpu_state(regs, fp);
+               err |= __put_user(fp, &sf->fpu_save);
        } else {
                err |= __put_user(0, &sf->fpu_save);
        }
+       if (wsaved) {
+               __siginfo_rwin_t __user *rwp = tail;
+               tail += sizeof(*rwp);
+               err |= save_rwin_state(wsaved, rwp);
+               err |= __put_user(rwp, &sf->rwin_save);
+       } else {
+               err |= __put_user(0, &sf->rwin_save);
+       }
 
        err |= __put_user(oldset->sig[0], &sf->info.si_mask);
        err |= __copy_to_user(sf->extramask, &oldset->sig[1],
                              (_NSIG_WORDS - 1) * sizeof(unsigned int));
-       err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
-                             sizeof(struct reg_window32));
+       if (!wsaved) {
+               err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
+                                     sizeof(struct reg_window32));
+       } else {
+               struct reg_window32 *rp;
+
+               rp = &current_thread_info()->reg_window[wsaved - 1];
+               err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
+       }
        if (err)
                goto sigsegv;
        
@@ -399,21 +365,24 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
                          int signo, sigset_t *oldset, siginfo_t *info)
 {
        struct rt_signal_frame __user *sf;
-       int sigframe_size;
+       int sigframe_size, wsaved;
+       void __user *tail;
        unsigned int psr;
        int err;
 
        synchronize_user_stack();
-       sigframe_size = RT_ALIGNEDSZ;
-       if (!used_math())
-               sigframe_size -= sizeof(__siginfo_fpu_t);
+       wsaved = current_thread_info()->w_saved;
+       sigframe_size = sizeof(*sf);
+       if (used_math())
+               sigframe_size += sizeof(__siginfo_fpu_t);
+       if (wsaved)
+               sigframe_size += sizeof(__siginfo_rwin_t);
        sf = (struct rt_signal_frame __user *)
                get_sigframe(&ka->sa, regs, sigframe_size);
        if (invalid_frame_pointer(sf, sigframe_size))
                goto sigill;
-       if (current_thread_info()->w_saved != 0)
-               goto sigill;
 
+       tail = sf + 1;
        err  = __put_user(regs->pc, &sf->regs.pc);
        err |= __put_user(regs->npc, &sf->regs.npc);
        err |= __put_user(regs->y, &sf->regs.y);
@@ -425,11 +394,21 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
        err |= __put_user(0, &sf->extra_size);
 
        if (psr & PSR_EF) {
-               err |= save_fpu_state(regs, &sf->fpu_state);
-               err |= __put_user(&sf->fpu_state, &sf->fpu_save);
+               __siginfo_fpu_t *fp = tail;
+               tail += sizeof(*fp);
+               err |= save_fpu_state(regs, fp);
+               err |= __put_user(fp, &sf->fpu_save);
        } else {
                err |= __put_user(0, &sf->fpu_save);
        }
+       if (wsaved) {
+               __siginfo_rwin_t *rwp = tail;
+               tail += sizeof(*rwp);
+               err |= save_rwin_state(wsaved, rwp);
+               err |= __put_user(rwp, &sf->rwin_save);
+       } else {
+               err |= __put_user(0, &sf->rwin_save);
+       }
        err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
        
        /* Setup sigaltstack */
@@ -437,8 +416,15 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
        err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
        err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
        
-       err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
-                             sizeof(struct reg_window32));
+       if (!wsaved) {
+               err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
+                                     sizeof(struct reg_window32));
+       } else {
+               struct reg_window32 *rp;
+
+               rp = &current_thread_info()->reg_window[wsaved - 1];
+               err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
+       }
 
        err |= copy_siginfo_to_user(&sf->info, info);
 
index 006fe45..47509df 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "entry.h"
 #include "systbls.h"
+#include "sigutil.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
@@ -236,7 +237,7 @@ struct rt_signal_frame {
        __siginfo_fpu_t __user  *fpu_save;
        stack_t                 stack;
        sigset_t                mask;
-       __siginfo_fpu_t         fpu_state;
+       __siginfo_rwin_t        *rwin_save;
 };
 
 static long _sigpause_common(old_sigset_t set)
@@ -266,33 +267,12 @@ asmlinkage long sys_sigsuspend(old_sigset_t set)
        return _sigpause_common(set);
 }
 
-static inline int
-restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
-{
-       unsigned long *fpregs = current_thread_info()->fpregs;
-       unsigned long fprs;
-       int err;
-
-       err = __get_user(fprs, &fpu->si_fprs);
-       fprs_write(0);
-       regs->tstate &= ~TSTATE_PEF;
-       if (fprs & FPRS_DL)
-               err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
-                              (sizeof(unsigned int) * 32));
-       if (fprs & FPRS_DU)
-               err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
-                              (sizeof(unsigned int) * 32));
-       err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
-       err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
-       current_thread_info()->fpsaved[0] |= fprs;
-       return err;
-}
-
 void do_rt_sigreturn(struct pt_regs *regs)
 {
        struct rt_signal_frame __user *sf;
        unsigned long tpc, tnpc, tstate;
        __siginfo_fpu_t __user *fpu_save;
+       __siginfo_rwin_t __user *rwin_save;
        sigset_t set;
        int err;
 
@@ -325,8 +305,8 @@ void do_rt_sigreturn(struct pt_regs *regs)
        regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
 
        err |= __get_user(fpu_save, &sf->fpu_save);
-       if (fpu_save)
-               err |= restore_fpu_state(regs, &sf->fpu_state);
+       if (!err && fpu_save)
+               err |= restore_fpu_state(regs, fpu_save);
 
        err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
        err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
@@ -334,6 +314,12 @@ void do_rt_sigreturn(struct pt_regs *regs)
        if (err)
                goto segv;
 
+       err |= __get_user(rwin_save, &sf->rwin_save);
+       if (!err && rwin_save) {
+               if (restore_rwin_state(rwin_save))
+                       goto segv;
+       }
+
        regs->tpc = tpc;
        regs->tnpc = tnpc;
 
@@ -351,34 +337,13 @@ segv:
 }
 
 /* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp, int fplen)
+static int invalid_frame_pointer(void __user *fp)
 {
        if (((unsigned long) fp) & 15)
                return 1;
        return 0;
 }
 
-static inline int
-save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
-{
-       unsigned long *fpregs = current_thread_info()->fpregs;
-       unsigned long fprs;
-       int err = 0;
-       
-       fprs = current_thread_info()->fpsaved[0];
-       if (fprs & FPRS_DL)
-               err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
-                                   (sizeof(unsigned int) * 32));
-       if (fprs & FPRS_DU)
-               err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
-                                   (sizeof(unsigned int) * 32));
-       err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
-       err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
-       err |= __put_user(fprs, &fpu->si_fprs);
-
-       return err;
-}
-
 static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize)
 {
        unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
@@ -414,34 +379,48 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
               int signo, sigset_t *oldset, siginfo_t *info)
 {
        struct rt_signal_frame __user *sf;
-       int sigframe_size, err;
+       int wsaved, err, sf_size;
+       void __user *tail;
 
        /* 1. Make sure everything is clean */
        synchronize_user_stack();
        save_and_clear_fpu();
        
-       sigframe_size = sizeof(struct rt_signal_frame);
-       if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
-               sigframe_size -= sizeof(__siginfo_fpu_t);
+       wsaved = get_thread_wsaved();
 
+       sf_size = sizeof(struct rt_signal_frame);
+       if (current_thread_info()->fpsaved[0] & FPRS_FEF)
+               sf_size += sizeof(__siginfo_fpu_t);
+       if (wsaved)
+               sf_size += sizeof(__siginfo_rwin_t);
        sf = (struct rt_signal_frame __user *)
-               get_sigframe(ka, regs, sigframe_size);
-       
-       if (invalid_frame_pointer (sf, sigframe_size))
-               goto sigill;
+               get_sigframe(ka, regs, sf_size);
 
-       if (get_thread_wsaved() != 0)
+       if (invalid_frame_pointer (sf))
                goto sigill;
 
+       tail = (sf + 1);
+
        /* 2. Save the current process state */
        err = copy_to_user(&sf->regs, regs, sizeof (*regs));
 
        if (current_thread_info()->fpsaved[0] & FPRS_FEF) {
-               err |= save_fpu_state(regs, &sf->fpu_state);
-               err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
+               __siginfo_fpu_t __user *fpu_save = tail;
+               tail += sizeof(__siginfo_fpu_t);
+               err |= save_fpu_state(regs, fpu_save);
+               err |= __put_user((u64)fpu_save, &sf->fpu_save);
        } else {
                err |= __put_user(0, &sf->fpu_save);
        }
+       if (wsaved) {
+               __siginfo_rwin_t __user *rwin_save = tail;
+               tail += sizeof(__siginfo_rwin_t);
+               err |= save_rwin_state(wsaved, rwin_save);
+               err |= __put_user((u64)rwin_save, &sf->rwin_save);
+               set_thread_wsaved(0);
+       } else {
+               err |= __put_user(0, &sf->rwin_save);
+       }
        
        /* Setup sigaltstack */
        err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
@@ -450,10 +429,17 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
 
        err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t));
 
-       err |= copy_in_user((u64 __user *)sf,
-                           (u64 __user *)(regs->u_regs[UREG_FP]+STACK_BIAS),
-                           sizeof(struct reg_window));
+       if (!wsaved) {
+               err |= copy_in_user((u64 __user *)sf,
+                                   (u64 __user *)(regs->u_regs[UREG_FP] +
+                                                  STACK_BIAS),
+                                   sizeof(struct reg_window));
+       } else {
+               struct reg_window *rp;
 
+               rp = &current_thread_info()->reg_window[wsaved - 1];
+               err |= copy_to_user(sf, rp, sizeof(struct reg_window));
+       }
        if (info)
                err |= copy_siginfo_to_user(&sf->info, info);
        else {
diff --git a/arch/sparc/kernel/sigutil.h b/arch/sparc/kernel/sigutil.h
new file mode 100644 (file)
index 0000000..d223aa4
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _SIGUTIL_H
+#define _SIGUTIL_H
+
+int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu);
+int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu);
+int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin);
+int restore_rwin_state(__siginfo_rwin_t __user *rp);
+
+#endif /* _SIGUTIL_H */
diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c
new file mode 100644 (file)
index 0000000..35c7897
--- /dev/null
@@ -0,0 +1,120 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/thread_info.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+
+#include <asm/sigcontext.h>
+#include <asm/fpumacro.h>
+#include <asm/ptrace.h>
+
+#include "sigutil.h"
+
+int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+{
+       int err = 0;
+#ifdef CONFIG_SMP
+       if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
+               put_psr(get_psr() | PSR_EF);
+               fpsave(&current->thread.float_regs[0], &current->thread.fsr,
+                      &current->thread.fpqueue[0], &current->thread.fpqdepth);
+               regs->psr &= ~(PSR_EF);
+               clear_tsk_thread_flag(current, TIF_USEDFPU);
+       }
+#else
+       if (current == last_task_used_math) {
+               put_psr(get_psr() | PSR_EF);
+               fpsave(&current->thread.float_regs[0], &current->thread.fsr,
+                      &current->thread.fpqueue[0], &current->thread.fpqdepth);
+               last_task_used_math = NULL;
+               regs->psr &= ~(PSR_EF);
+       }
+#endif
+       err |= __copy_to_user(&fpu->si_float_regs[0],
+                             &current->thread.float_regs[0],
+                             (sizeof(unsigned long) * 32));
+       err |= __put_user(current->thread.fsr, &fpu->si_fsr);
+       err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
+       if (current->thread.fpqdepth != 0)
+               err |= __copy_to_user(&fpu->si_fpqueue[0],
+                                     &current->thread.fpqueue[0],
+                                     ((sizeof(unsigned long) +
+                                     (sizeof(unsigned long *)))*16));
+       clear_used_math();
+       return err;
+}
+
+int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+{
+       int err;
+#ifdef CONFIG_SMP
+       if (test_tsk_thread_flag(current, TIF_USEDFPU))
+               regs->psr &= ~PSR_EF;
+#else
+       if (current == last_task_used_math) {
+               last_task_used_math = NULL;
+               regs->psr &= ~PSR_EF;
+       }
+#endif
+       set_used_math();
+       clear_tsk_thread_flag(current, TIF_USEDFPU);
+
+       if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu)))
+               return -EFAULT;
+
+       err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
+                              (sizeof(unsigned long) * 32));
+       err |= __get_user(current->thread.fsr, &fpu->si_fsr);
+       err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
+       if (current->thread.fpqdepth != 0)
+               err |= __copy_from_user(&current->thread.fpqueue[0],
+                                       &fpu->si_fpqueue[0],
+                                       ((sizeof(unsigned long) +
+                                       (sizeof(unsigned long *)))*16));
+       return err;
+}
+
+int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
+{
+       int i, err = __put_user(wsaved, &rwin->wsaved);
+
+       for (i = 0; i < wsaved; i++) {
+               struct reg_window32 *rp;
+               unsigned long fp;
+
+               rp = &current_thread_info()->reg_window[i];
+               fp = current_thread_info()->rwbuf_stkptrs[i];
+               err |= copy_to_user(&rwin->reg_window[i], rp,
+                                   sizeof(struct reg_window32));
+               err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
+       }
+       return err;
+}
+
+int restore_rwin_state(__siginfo_rwin_t __user *rp)
+{
+       struct thread_info *t = current_thread_info();
+       int i, wsaved, err;
+
+       __get_user(wsaved, &rp->wsaved);
+       if (wsaved > NSWINS)
+               return -EFAULT;
+
+       err = 0;
+       for (i = 0; i < wsaved; i++) {
+               err |= copy_from_user(&t->reg_window[i],
+                                     &rp->reg_window[i],
+                                     sizeof(struct reg_window32));
+               err |= __get_user(t->rwbuf_stkptrs[i],
+                                 &rp->rwbuf_stkptrs[i]);
+       }
+       if (err)
+               return err;
+
+       t->w_saved = wsaved;
+       synchronize_user_stack();
+       if (t->w_saved)
+               return -EFAULT;
+       return 0;
+
+}
diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c
new file mode 100644 (file)
index 0000000..e7dc508
--- /dev/null
@@ -0,0 +1,93 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/thread_info.h>
+#include <linux/uaccess.h>
+
+#include <asm/sigcontext.h>
+#include <asm/fpumacro.h>
+#include <asm/ptrace.h>
+
+#include "sigutil.h"
+
+int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+{
+       unsigned long *fpregs = current_thread_info()->fpregs;
+       unsigned long fprs;
+       int err = 0;
+       
+       fprs = current_thread_info()->fpsaved[0];
+       if (fprs & FPRS_DL)
+               err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
+                                   (sizeof(unsigned int) * 32));
+       if (fprs & FPRS_DU)
+               err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
+                                   (sizeof(unsigned int) * 32));
+       err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
+       err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
+       err |= __put_user(fprs, &fpu->si_fprs);
+
+       return err;
+}
+
+int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+{
+       unsigned long *fpregs = current_thread_info()->fpregs;
+       unsigned long fprs;
+       int err;
+
+       err = __get_user(fprs, &fpu->si_fprs);
+       fprs_write(0);
+       regs->tstate &= ~TSTATE_PEF;
+       if (fprs & FPRS_DL)
+               err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
+                              (sizeof(unsigned int) * 32));
+       if (fprs & FPRS_DU)
+               err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
+                              (sizeof(unsigned int) * 32));
+       err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
+       err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
+       current_thread_info()->fpsaved[0] |= fprs;
+       return err;
+}
+
+int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
+{
+       int i, err = __put_user(wsaved, &rwin->wsaved);
+
+       for (i = 0; i < wsaved; i++) {
+               struct reg_window *rp = &current_thread_info()->reg_window[i];
+               unsigned long fp = current_thread_info()->rwbuf_stkptrs[i];
+
+               err |= copy_to_user(&rwin->reg_window[i], rp,
+                                   sizeof(struct reg_window));
+               err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
+       }
+       return err;
+}
+
+int restore_rwin_state(__siginfo_rwin_t __user *rp)
+{
+       struct thread_info *t = current_thread_info();
+       int i, wsaved, err;
+
+       __get_user(wsaved, &rp->wsaved);
+       if (wsaved > NSWINS)
+               return -EFAULT;
+
+       err = 0;
+       for (i = 0; i < wsaved; i++) {
+               err |= copy_from_user(&t->reg_window[i],
+                                     &rp->reg_window[i],
+                                     sizeof(struct reg_window));
+               err |= __get_user(t->rwbuf_stkptrs[i],
+                                 &rp->rwbuf_stkptrs[i]);
+       }
+       if (err)
+               return err;
+
+       set_thread_wsaved(wsaved);
+       synchronize_user_stack();
+       if (get_thread_wsaved())
+               return -EFAULT;
+       return 0;
+}
index 44e5faf..d97f3eb 100644 (file)
@@ -81,7 +81,6 @@ SIGN2(sys32_fadvise64, compat_sys_fadvise64, %o0, %o4)
 SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5)
 SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1)
 SIGN1(sys32_mlockall, sys_mlockall, %o0)
-SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0)
 SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1)
 SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1)
 SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
index 6e492d5..09d8ec4 100644 (file)
@@ -67,7 +67,7 @@ sys_call_table:
 /*235*/        .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/        .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 /*245*/        .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
-/*250*/        .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+/*250*/        .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_ni_syscall
 /*255*/        .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/        .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 /*265*/        .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
index f566518..edbec45 100644 (file)
@@ -68,7 +68,7 @@ sys_call_table32:
        .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
 /*240*/        .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
        .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
-/*250*/        .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
+/*250*/        .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys_nis_syscall
        .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
 /*260*/        .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
        .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
@@ -145,7 +145,7 @@ sys_call_table:
        .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/        .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
        .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
-/*250*/        .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+/*250*/        .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nis_syscall
        .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/        .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
        .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
index a0e866d..54edb20 100644 (file)
@@ -672,7 +672,7 @@ ia32_sys_call_table:
        .quad sys32_vm86_warning        /* vm86 */ 
        .quad quiet_ni_syscall  /* query_module */
        .quad sys_poll
-       .quad compat_sys_nfsservctl
+       .quad quiet_ni_syscall /* old nfsservctl */
        .quad sys_setresgid16   /* 170 */
        .quad sys_getresgid16
        .quad sys_prctl
index a518c0a..c59cc97 100644 (file)
@@ -44,7 +44,7 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
                : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
 #elif defined(__x86_64__)
        __asm__ (
-               "mul %[mul_frac] ; shrd $32, %[hi], %[lo]"
+               "mulq %[mul_frac] ; shrd $32, %[hi], %[lo]"
                : [lo]"=a"(product),
                  [hi]"=d"(tmp)
                : "0"(delta),
index d92641c..2010405 100644 (file)
@@ -414,7 +414,7 @@ __SYSCALL(__NR_query_module, sys_ni_syscall)
 __SYSCALL(__NR_quotactl, sys_quotactl)
 
 #define __NR_nfsservctl                                180
-__SYSCALL(__NR_nfsservctl, sys_nfsservctl)
+__SYSCALL(__NR_nfsservctl, sys_ni_syscall)
 
 /* reserved for LiS/STREAMS */
 #define __NR_getpmsg                           181
index 64a619d..7ff4669 100644 (file)
@@ -39,7 +39,7 @@ typedef struct xpaddr {
     ((unsigned long)((u64)CONFIG_XEN_MAX_DOMAIN_MEMORY * 1024 * 1024 * 1024 / PAGE_SIZE))
 
 extern unsigned long *machine_to_phys_mapping;
-extern unsigned int   machine_to_phys_order;
+extern unsigned long  machine_to_phys_nr;
 
 extern unsigned long get_phys_to_machine(unsigned long pfn);
 extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
@@ -87,7 +87,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return mfn;
 
-       if (unlikely((mfn >> machine_to_phys_order) != 0)) {
+       if (unlikely(mfn >= machine_to_phys_nr)) {
                pfn = ~0;
                goto try_override;
        }
index adc66c3..34b1859 100644 (file)
@@ -207,7 +207,6 @@ static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_ri
            ((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
            APIC_DM_INIT;
        uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
-       mdelay(10);
 
        val = (1UL << UVH_IPI_INT_SEND_SHFT) |
            (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
index 08119a3..6b96110 100644 (file)
@@ -149,7 +149,6 @@ struct set_mtrr_data {
  */
 static int mtrr_rendezvous_handler(void *info)
 {
-#ifdef CONFIG_SMP
        struct set_mtrr_data *data = info;
 
        /*
@@ -171,7 +170,6 @@ static int mtrr_rendezvous_handler(void *info)
        } else if (mtrr_aps_delayed_init || !cpu_online(smp_processor_id())) {
                mtrr_if->set_all();
        }
-#endif
        return 0;
 }
 
index 4ee3abf..cfa62ec 100644 (file)
@@ -1900,6 +1900,9 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 
        perf_callchain_store(entry, regs->ip);
 
+       if (!current->mm)
+               return;
+
        if (perf_callchain_user32(regs, entry))
                return;
 
index 5c1a919..f3f6f53 100644 (file)
@@ -54,6 +54,7 @@
 #include <asm/ftrace.h>
 #include <asm/irq_vectors.h>
 #include <asm/cpufeature.h>
+#include <asm/alternative-asm.h>
 
 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
 #include <linux/elf-em.h>
@@ -873,12 +874,7 @@ ENTRY(simd_coprocessor_error)
 661:   pushl_cfi $do_general_protection
 662:
 .section .altinstructions,"a"
-       .balign 4
-       .long 661b
-       .long 663f
-       .word X86_FEATURE_XMM
-       .byte 662b-661b
-       .byte 664f-663f
+       altinstruction_entry 661b, 663f, X86_FEATURE_XMM, 662b-661b, 664f-663f
 .previous
 .section .altinstr_replacement,"ax"
 663:   pushl $do_simd_coprocessor_error
index fbb0a04..bc19be3 100644 (file)
@@ -168,7 +168,7 @@ ENTRY(sys_call_table)
        .long ptregs_vm86
        .long sys_ni_syscall    /* Old sys_query_module */
        .long sys_poll
-       .long sys_nfsservctl
+       .long sys_ni_syscall    /* Old nfsservctl */
        .long sys_setresgid16   /* 170 */
        .long sys_getresgid16
        .long sys_prctl
index 988724b..ff5790d 100644 (file)
@@ -22,6 +22,8 @@ config KVM
        depends on HAVE_KVM
        # for device assignment:
        depends on PCI
+       # for TASKSTATS/TASK_DELAY_ACCT:
+       depends on NET
        select PREEMPT_NOTIFIERS
        select MMU_NOTIFIER
        select ANON_INODES
@@ -31,6 +33,7 @@ config KVM
        select KVM_ASYNC_PF
        select USER_RETURN_NOTIFIER
        select KVM_MMIO
+       select TASKSTATS
        select TASK_DELAY_ACCT
        ---help---
          Support hosting fully virtualized guest machines using hardware
index 247aae3..0d17c8c 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/traps.h>                 /* dotraplinkage, ...           */
 #include <asm/pgalloc.h>               /* pgd_*(), ...                 */
 #include <asm/kmemcheck.h>             /* kmemcheck_*(), ...           */
+#include <asm/vsyscall.h>
 
 /*
  * Page fault error code bits:
index ae3cb23..039d913 100644 (file)
@@ -360,6 +360,20 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
                }
        }
 
+       /* After the PCI-E bus has been walked and all devices discovered,
+        * configure any settings of the fabric that might be necessary.
+        */
+       if (bus) {
+               struct pci_bus *child;
+               list_for_each_entry(child, &bus->children, node) {
+                       struct pci_dev *self = child->self;
+                       if (!self)
+                               continue;
+
+                       pcie_bus_configure_settings(child, self->pcie_mpss);
+               }
+       }
+
        if (!bus)
                kfree(sd);
 
index 7000e74..58425ad 100644 (file)
@@ -689,7 +689,9 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
                        irq_attr.trigger = 1;
                        irq_attr.polarity = 1;
                        io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr);
-               }
+               } else
+                       pentry->irq = 0; /* No irq */
+
                switch (pentry->type) {
                case SFI_DEV_TYPE_IPC:
                        /* ID as IRQ is a hack that will go away */
index 8b9940e..7cce722 100644 (file)
@@ -161,13 +161,13 @@ restart:
        if (inbuf && inlen) {
                /* write data to EC */
                for (i = 0; i < inlen; i++) {
+                       pr_devel("olpc-ec:  sending cmd arg 0x%x\n", inbuf[i]);
+                       outb(inbuf[i], 0x68);
                        if (wait_on_ibf(0x6c, 0)) {
                                printk(KERN_ERR "olpc-ec:  timeout waiting for"
                                                " EC accept data!\n");
                                goto err;
                        }
-                       pr_devel("olpc-ec:  sending cmd arg 0x%x\n", inbuf[i]);
-                       outb(inbuf[i], 0x68);
                }
        }
        if (outbuf && outlen) {
index e2800af..e354bce 100644 (file)
@@ -43,7 +43,7 @@ __kernel_vsyscall:
        .space 7,0x90
 
        /* 14: System call restart point is here! (SYSENTER_RETURN-2) */
-       jmp .Lenter_kernel
+       int $0x80
        /* 16: System call normal return point is here! */
 VDSO32_SYSENTER_RETURN:        /* Symbol used by sysenter.c via vdso32-syms.h */
        pop %ebp
index 3326204..add2c2d 100644 (file)
@@ -15,7 +15,7 @@ obj-y         := enlighten.o setup.o multicalls.o mmu.o irq.o \
                        grant-table.o suspend.o platform-pci-unplug.o \
                        p2m.o
 
-obj-$(CONFIG_FTRACE) += trace.o
+obj-$(CONFIG_EVENT_TRACING) += trace.o
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
index e2345af..2d69617 100644 (file)
@@ -77,8 +77,8 @@ EXPORT_SYMBOL_GPL(xen_domain_type);
 
 unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
 EXPORT_SYMBOL(machine_to_phys_mapping);
-unsigned int   machine_to_phys_order;
-EXPORT_SYMBOL(machine_to_phys_order);
+unsigned long  machine_to_phys_nr;
+EXPORT_SYMBOL(machine_to_phys_nr);
 
 struct start_info *xen_start_info;
 EXPORT_SYMBOL_GPL(xen_start_info);
index 8cce339..20a6142 100644 (file)
@@ -1713,15 +1713,19 @@ static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
 void __init xen_setup_machphys_mapping(void)
 {
        struct xen_machphys_mapping mapping;
-       unsigned long machine_to_phys_nr_ents;
 
        if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
                machine_to_phys_mapping = (unsigned long *)mapping.v_start;
-               machine_to_phys_nr_ents = mapping.max_mfn + 1;
+               machine_to_phys_nr = mapping.max_mfn + 1;
        } else {
-               machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
+               machine_to_phys_nr = MACH2PHYS_NR_ENTRIES;
        }
-       machine_to_phys_order = fls(machine_to_phys_nr_ents - 1);
+#ifdef CONFIG_X86_32
+       if ((machine_to_phys_mapping + machine_to_phys_nr)
+           < machine_to_phys_mapping)
+               machine_to_phys_nr = (unsigned long *)NULL
+                                    - machine_to_phys_mapping;
+#endif
 }
 
 #ifdef CONFIG_X86_64
index df118a8..c3b8d44 100644 (file)
@@ -184,6 +184,19 @@ static unsigned long __init xen_set_identity(const struct e820entry *list,
                                        PFN_UP(start_pci), PFN_DOWN(last));
        return identity;
 }
+
+static unsigned long __init xen_get_max_pages(void)
+{
+       unsigned long max_pages = MAX_DOMAIN_PAGES;
+       domid_t domid = DOMID_SELF;
+       int ret;
+
+       ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid);
+       if (ret > 0)
+               max_pages = ret;
+       return min(max_pages, MAX_DOMAIN_PAGES);
+}
+
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
@@ -292,6 +305,12 @@ char * __init xen_memory_setup(void)
 
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
+       extra_limit = xen_get_max_pages();
+       if (extra_limit >= max_pfn)
+               extra_pages = extra_limit - max_pfn;
+       else
+               extra_pages = 0;
+
        extra_pages += xen_return_unused_memory(xen_start_info->nr_pages, &e820);
 
        /*
index b4533a8..d4fc6d4 100644 (file)
@@ -32,6 +32,7 @@
 #include <xen/page.h>
 #include <xen/events.h>
 
+#include <xen/hvc-console.h>
 #include "xen-ops.h"
 #include "mmu.h"
 
@@ -207,6 +208,15 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
        unsigned cpu;
        unsigned int i;
 
+       if (skip_ioapic_setup) {
+               char *m = (max_cpus == 0) ?
+                       "The nosmp parameter is incompatible with Xen; " \
+                       "use Xen dom0_max_vcpus=1 parameter" :
+                       "The noapic parameter is incompatible with Xen";
+
+               xen_raw_printk(m);
+               panic(m);
+       }
        xen_init_lock_cpu(0);
 
        smp_store_cpu_info(0);
@@ -521,8 +531,6 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
        native_smp_prepare_cpus(max_cpus);
        WARN_ON(xen_smp_intr_init(0));
 
-       if (!xen_have_vector_callback)
-               return;
        xen_init_lock_cpu(0);
        xen_init_spinlocks();
 }
@@ -546,6 +554,8 @@ static void xen_hvm_cpu_die(unsigned int cpu)
 
 void __init xen_hvm_smp_init(void)
 {
+       if (!xen_have_vector_callback)
+               return;
        smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
        smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
        smp_ops.cpu_up = xen_hvm_cpu_up;
index 22a2093..b040b0e 100644 (file)
@@ -113,11 +113,13 @@ xen_iret_start_crit:
 
        /*
         * If there's something pending, mask events again so we can
-        * jump back into xen_hypervisor_callback
+        * jump back into xen_hypervisor_callback. Otherwise do not
+        * touch XEN_vcpu_info_mask.
         */
-       sete XEN_vcpu_info_mask(%eax)
+       jne 1f
+       movb $1, XEN_vcpu_info_mask(%eax)
 
-       popl %eax
+1:     popl %eax
 
        /*
         * From this point on the registers are restored and the stack
index a6f934f..798ee6d 100644 (file)
@@ -455,7 +455,7 @@ __SYSCALL(203, sys_reboot, 3)
 #define __NR_quotactl                          204
 __SYSCALL(204, sys_quotactl, 4)
 #define __NR_nfsservctl                        205
-__SYSCALL(205, sys_nfsservctl, 3)
+__SYSCALL(205, sys_ni_syscall, 0)
 #define __NR__sysctl                           206
 __SYSCALL(206, sys_sysctl, 1)
 #define __NR_bdflush                           207
index 60be1e0..e97934e 100644 (file)
@@ -65,6 +65,16 @@ config BLK_DEV_BSG
 
          If unsure, say Y.
 
+config BLK_DEV_BSGLIB
+       bool "Block layer SG support v4 helper lib"
+       default n
+       select BLK_DEV_BSG
+       help
+         Subsystems will normally enable this if needed. Users will not
+         normally need to manually enable this.
+
+         If unsure, say N.
+
 config BLK_DEV_INTEGRITY
        bool "Block layer data integrity support"
        ---help---
index 0fec4b3..514c6e4 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
                        blk-iopoll.o blk-lib.o ioctl.o genhd.o scsi_ioctl.o
 
 obj-$(CONFIG_BLK_DEV_BSG)      += bsg.o
+obj-$(CONFIG_BLK_DEV_BSGLIB)   += bsg-lib.o
 obj-$(CONFIG_BLK_CGROUP)       += blk-cgroup.o
 obj-$(CONFIG_BLK_DEV_THROTTLING)       += blk-throttle.o
 obj-$(CONFIG_IOSCHED_NOOP)     += noop-iosched.o
index b627558..90e1ffd 100644 (file)
@@ -1702,6 +1702,7 @@ EXPORT_SYMBOL_GPL(blk_rq_check_limits);
 int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
 {
        unsigned long flags;
+       int where = ELEVATOR_INSERT_BACK;
 
        if (blk_rq_check_limits(q, rq))
                return -EIO;
@@ -1718,7 +1719,10 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
         */
        BUG_ON(blk_queued_rq(rq));
 
-       add_acct_request(q, rq, ELEVATOR_INSERT_BACK);
+       if (rq->cmd_flags & (REQ_FLUSH|REQ_FUA))
+               where = ELEVATOR_INSERT_FLUSH;
+
+       add_acct_request(q, rq, where);
        spin_unlock_irqrestore(q->queue_lock, flags);
 
        return 0;
@@ -2275,7 +2279,7 @@ static bool blk_end_bidi_request(struct request *rq, int error,
  *     %false - we are done with this request
  *     %true  - still buffers pending for this request
  **/
-static bool __blk_end_bidi_request(struct request *rq, int error,
+bool __blk_end_bidi_request(struct request *rq, int error,
                                   unsigned int nr_bytes, unsigned int bidi_bytes)
 {
        if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes))
index bb21e4c..491eb30 100644 (file)
@@ -95,11 +95,12 @@ static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq)
 {
        unsigned int policy = 0;
 
+       if (blk_rq_sectors(rq))
+               policy |= REQ_FSEQ_DATA;
+
        if (fflags & REQ_FLUSH) {
                if (rq->cmd_flags & REQ_FLUSH)
                        policy |= REQ_FSEQ_PREFLUSH;
-               if (blk_rq_sectors(rq))
-                       policy |= REQ_FSEQ_DATA;
                if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA))
                        policy |= REQ_FSEQ_POSTFLUSH;
        }
@@ -122,7 +123,7 @@ static void blk_flush_restore_request(struct request *rq)
 
        /* make @rq a normal request */
        rq->cmd_flags &= ~REQ_FLUSH_SEQ;
-       rq->end_io = NULL;
+       rq->end_io = rq->flush.saved_end_io;
 }
 
 /**
@@ -300,9 +301,6 @@ void blk_insert_flush(struct request *rq)
        unsigned int fflags = q->flush_flags;   /* may change, cache */
        unsigned int policy = blk_flush_policy(fflags, rq);
 
-       BUG_ON(rq->end_io);
-       BUG_ON(!rq->bio || rq->bio != rq->biotail);
-
        /*
         * @policy now records what operations need to be done.  Adjust
         * REQ_FLUSH and FUA for the driver.
@@ -311,6 +309,19 @@ void blk_insert_flush(struct request *rq)
        if (!(fflags & REQ_FUA))
                rq->cmd_flags &= ~REQ_FUA;
 
+       /*
+        * An empty flush handed down from a stacking driver may
+        * translate into nothing if the underlying device does not
+        * advertise a write-back cache.  In this case, simply
+        * complete the request.
+        */
+       if (!policy) {
+               __blk_end_bidi_request(rq, 0, 0, 0);
+               return;
+       }
+
+       BUG_ON(!rq->bio || rq->bio != rq->biotail);
+
        /*
         * If there's data but flush is not necessary, the request can be
         * processed directly without going through flush machinery.  Queue
@@ -319,6 +330,7 @@ void blk_insert_flush(struct request *rq)
        if ((policy & REQ_FSEQ_DATA) &&
            !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
                list_add_tail(&rq->queuelist, &q->queue_head);
+               blk_run_queue_async(q);
                return;
        }
 
@@ -329,6 +341,7 @@ void blk_insert_flush(struct request *rq)
        memset(&rq->flush, 0, sizeof(rq->flush));
        INIT_LIST_HEAD(&rq->flush.list);
        rq->cmd_flags |= REQ_FLUSH_SEQ;
+       rq->flush.saved_end_io = rq->end_io; /* Usually NULL */
        rq->end_io = flush_data_end_io;
 
        blk_flush_complete_seq(rq, REQ_FSEQ_ACTIONS & ~policy, 0);
index 475fab8..58340d0 100644 (file)
@@ -124,6 +124,14 @@ void __blk_complete_request(struct request *req)
        } else
                ccpu = cpu;
 
+       /*
+        * If current CPU and requested CPU are in the same group, running
+        * softirq in current CPU. One might concern this is just like
+        * QUEUE_FLAG_SAME_FORCE, but actually not. blk_complete_request() is
+        * running in interrupt handler, and currently I/O controller doesn't
+        * support multiple interrupts, so current CPU is unique actually. This
+        * avoids IPI sending from current CPU to the first CPU of a group.
+        */
        if (ccpu == cpu || ccpu == group_cpu) {
                struct list_head *list;
 do_local:
index f6a7941..a19f58c 100644 (file)
@@ -746,7 +746,7 @@ static bool tg_may_dispatch(struct throtl_data *td, struct throtl_grp *tg,
 static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
 {
        bool rw = bio_data_dir(bio);
-       bool sync = bio->bi_rw & REQ_SYNC;
+       bool sync = rw_is_sync(bio->bi_rw);
 
        /* Charge the bio to the group */
        tg->bytes_disp[rw] += bio->bi_size;
@@ -1150,7 +1150,7 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop)
 
                if (tg_no_rule_group(tg, rw)) {
                        blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size,
-                                       rw, bio->bi_rw & REQ_SYNC);
+                                       rw, rw_is_sync(bio->bi_rw));
                        rcu_read_unlock();
                        return 0;
                }
index d658628..20b900a 100644 (file)
@@ -17,6 +17,8 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq,
                      struct bio *bio);
 void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
+bool __blk_end_bidi_request(struct request *rq, int error,
+                           unsigned int nr_bytes, unsigned int bidi_bytes);
 
 void blk_rq_timed_out_timer(unsigned long data);
 void blk_delete_timer(struct request *);
diff --git a/block/bsg-lib.c b/block/bsg-lib.c
new file mode 100644 (file)
index 0000000..6690e6e
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ *  BSG helper library
+ *
+ *  Copyright (C) 2008   James Smart, Emulex Corporation
+ *  Copyright (C) 2011   Red Hat, Inc.  All rights reserved.
+ *  Copyright (C) 2011   Mike Christie
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/bsg-lib.h>
+#include <linux/module.h>
+#include <scsi/scsi_cmnd.h>
+
+/**
+ * bsg_destroy_job - routine to teardown/delete a bsg job
+ * @job: bsg_job that is to be torn down
+ */
+static void bsg_destroy_job(struct bsg_job *job)
+{
+       put_device(job->dev);   /* release reference for the request */
+
+       kfree(job->request_payload.sg_list);
+       kfree(job->reply_payload.sg_list);
+       kfree(job);
+}
+
+/**
+ * bsg_job_done - completion routine for bsg requests
+ * @job: bsg_job that is complete
+ * @result: job reply result
+ * @reply_payload_rcv_len: length of payload recvd
+ *
+ * The LLD should call this when the bsg job has completed.
+ */
+void bsg_job_done(struct bsg_job *job, int result,
+                 unsigned int reply_payload_rcv_len)
+{
+       struct request *req = job->req;
+       struct request *rsp = req->next_rq;
+       int err;
+
+       err = job->req->errors = result;
+       if (err < 0)
+               /* we're only returning the result field in the reply */
+               job->req->sense_len = sizeof(u32);
+       else
+               job->req->sense_len = job->reply_len;
+       /* we assume all request payload was transferred, residual == 0 */
+       req->resid_len = 0;
+
+       if (rsp) {
+               WARN_ON(reply_payload_rcv_len > rsp->resid_len);
+
+               /* set reply (bidi) residual */
+               rsp->resid_len -= min(reply_payload_rcv_len, rsp->resid_len);
+       }
+       blk_complete_request(req);
+}
+EXPORT_SYMBOL_GPL(bsg_job_done);
+
+/**
+ * bsg_softirq_done - softirq done routine for destroying the bsg requests
+ * @rq: BSG request that holds the job to be destroyed
+ */
+static void bsg_softirq_done(struct request *rq)
+{
+       struct bsg_job *job = rq->special;
+
+       blk_end_request_all(rq, rq->errors);
+       bsg_destroy_job(job);
+}
+
+static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
+{
+       size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
+
+       BUG_ON(!req->nr_phys_segments);
+
+       buf->sg_list = kzalloc(sz, GFP_KERNEL);
+       if (!buf->sg_list)
+               return -ENOMEM;
+       sg_init_table(buf->sg_list, req->nr_phys_segments);
+       buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
+       buf->payload_len = blk_rq_bytes(req);
+       return 0;
+}
+
+/**
+ * bsg_create_job - create the bsg_job structure for the bsg request
+ * @dev: device that is being sent the bsg request
+ * @req: BSG request that needs a job structure
+ */
+static int bsg_create_job(struct device *dev, struct request *req)
+{
+       struct request *rsp = req->next_rq;
+       struct request_queue *q = req->q;
+       struct bsg_job *job;
+       int ret;
+
+       BUG_ON(req->special);
+
+       job = kzalloc(sizeof(struct bsg_job) + q->bsg_job_size, GFP_KERNEL);
+       if (!job)
+               return -ENOMEM;
+
+       req->special = job;
+       job->req = req;
+       if (q->bsg_job_size)
+               job->dd_data = (void *)&job[1];
+       job->request = req->cmd;
+       job->request_len = req->cmd_len;
+       job->reply = req->sense;
+       job->reply_len = SCSI_SENSE_BUFFERSIZE; /* Size of sense buffer
+                                                * allocated */
+       if (req->bio) {
+               ret = bsg_map_buffer(&job->request_payload, req);
+               if (ret)
+                       goto failjob_rls_job;
+       }
+       if (rsp && rsp->bio) {
+               ret = bsg_map_buffer(&job->reply_payload, rsp);
+               if (ret)
+                       goto failjob_rls_rqst_payload;
+       }
+       job->dev = dev;
+       /* take a reference for the request */
+       get_device(job->dev);
+       return 0;
+
+failjob_rls_rqst_payload:
+       kfree(job->request_payload.sg_list);
+failjob_rls_job:
+       kfree(job);
+       return -ENOMEM;
+}
+
+/*
+ * bsg_goose_queue - restart queue in case it was stopped
+ * @q: request q to be restarted
+ */
+void bsg_goose_queue(struct request_queue *q)
+{
+       if (!q)
+               return;
+
+       blk_run_queue_async(q);
+}
+EXPORT_SYMBOL_GPL(bsg_goose_queue);
+
+/**
+ * bsg_request_fn - generic handler for bsg requests
+ * @q: request queue to manage
+ *
+ * On error the create_bsg_job function should return a -Exyz error value
+ * that will be set to the req->errors.
+ *
+ * Drivers/subsys should pass this to the queue init function.
+ */
+void bsg_request_fn(struct request_queue *q)
+{
+       struct device *dev = q->queuedata;
+       struct request *req;
+       struct bsg_job *job;
+       int ret;
+
+       if (!get_device(dev))
+               return;
+
+       while (1) {
+               req = blk_fetch_request(q);
+               if (!req)
+                       break;
+               spin_unlock_irq(q->queue_lock);
+
+               ret = bsg_create_job(dev, req);
+               if (ret) {
+                       req->errors = ret;
+                       blk_end_request_all(req, ret);
+                       spin_lock_irq(q->queue_lock);
+                       continue;
+               }
+
+               job = req->special;
+               ret = q->bsg_job_fn(job);
+               spin_lock_irq(q->queue_lock);
+               if (ret)
+                       break;
+       }
+
+       spin_unlock_irq(q->queue_lock);
+       put_device(dev);
+       spin_lock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL_GPL(bsg_request_fn);
+
+/**
+ * bsg_setup_queue - Create and add the bsg hooks so we can receive requests
+ * @dev: device to attach bsg device to
+ * @q: request queue setup by caller
+ * @name: device to give bsg device
+ * @job_fn: bsg job handler
+ * @dd_job_size: size of LLD data needed for each job
+ *
+ * The caller should have setup the reuqest queue with bsg_request_fn
+ * as the request_fn.
+ */
+int bsg_setup_queue(struct device *dev, struct request_queue *q,
+                   char *name, bsg_job_fn *job_fn, int dd_job_size)
+{
+       int ret;
+
+       q->queuedata = dev;
+       q->bsg_job_size = dd_job_size;
+       q->bsg_job_fn = job_fn;
+       queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
+       blk_queue_softirq_done(q, bsg_softirq_done);
+       blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
+
+       ret = bsg_register_queue(q, dev, name, NULL);
+       if (ret) {
+               printk(KERN_ERR "%s: bsg interface failed to "
+                      "initialize - register queue\n", dev->kobj.name);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(bsg_setup_queue);
+
+/**
+ * bsg_remove_queue - Deletes the bsg dev from the q
+ * @q: the request_queue that is to be torn down.
+ *
+ * Notes:
+ *   Before unregistering the queue empty any requests that are blocked
+ */
+void bsg_remove_queue(struct request_queue *q)
+{
+       struct request *req; /* block request */
+       int counts; /* totals for request_list count and starved */
+
+       if (!q)
+               return;
+
+       /* Stop taking in new requests */
+       spin_lock_irq(q->queue_lock);
+       blk_stop_queue(q);
+
+       /* drain all requests in the queue */
+       while (1) {
+               /* need the lock to fetch a request
+                * this may fetch the same reqeust as the previous pass
+                */
+               req = blk_fetch_request(q);
+               /* save requests in use and starved */
+               counts = q->rq.count[0] + q->rq.count[1] +
+                        q->rq.starved[0] + q->rq.starved[1];
+               spin_unlock_irq(q->queue_lock);
+               /* any requests still outstanding? */
+               if (counts == 0)
+                       break;
+
+               /* This may be the same req as the previous iteration,
+                * always send the blk_end_request_all after a prefetch.
+                * It is not okay to not end the request because the
+                * prefetch started the request.
+                */
+               if (req) {
+                       /* return -ENXIO to indicate that this queue is
+                        * going away
+                        */
+                       req->errors = -ENXIO;
+                       blk_end_request_all(req, -ENXIO);
+               }
+
+               msleep(200); /* allow bsg to possibly finish */
+               spin_lock_irq(q->queue_lock);
+       }
+       bsg_unregister_queue(q);
+}
+EXPORT_SYMBOL_GPL(bsg_remove_queue);
index 1f96ad6..a33bd43 100644 (file)
@@ -130,6 +130,8 @@ struct cfq_queue {
        unsigned long slice_end;
        long slice_resid;
 
+       /* pending metadata requests */
+       int meta_pending;
        /* number of requests that are on the dispatch list or inside driver */
        int dispatched;
 
@@ -682,6 +684,9 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2,
        if (rq_is_sync(rq1) != rq_is_sync(rq2))
                return rq_is_sync(rq1) ? rq1 : rq2;
 
+       if ((rq1->cmd_flags ^ rq2->cmd_flags) & REQ_META)
+               return rq1->cmd_flags & REQ_META ? rq1 : rq2;
+
        s1 = blk_rq_pos(rq1);
        s2 = blk_rq_pos(rq2);
 
@@ -1209,6 +1214,9 @@ static void cfq_destroy_cfqg(struct cfq_data *cfqd, struct cfq_group *cfqg)
 
        hlist_del_init(&cfqg->cfqd_node);
 
+       BUG_ON(cfqd->nr_blkcg_linked_grps <= 0);
+       cfqd->nr_blkcg_linked_grps--;
+
        /*
         * Put the reference taken at the time of creation so that when all
         * queues are gone, group can be destroyed.
@@ -1604,6 +1612,10 @@ static void cfq_remove_request(struct request *rq)
        cfqq->cfqd->rq_queued--;
        cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
                                        rq_data_dir(rq), rq_is_sync(rq));
+       if (rq->cmd_flags & REQ_META) {
+               WARN_ON(!cfqq->meta_pending);
+               cfqq->meta_pending--;
+       }
 }
 
 static int cfq_merge(struct request_queue *q, struct request **req,
@@ -3356,6 +3368,13 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
            RB_EMPTY_ROOT(&cfqq->sort_list))
                return true;
 
+       /*
+        * So both queues are sync. Let the new request get disk time if
+        * it's a metadata request and the current queue is doing regular IO.
+        */
+       if ((rq->cmd_flags & REQ_META) && !cfqq->meta_pending)
+               return true;
+
        /*
         * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice.
         */
@@ -3420,6 +3439,8 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
        struct cfq_io_context *cic = RQ_CIC(rq);
 
        cfqd->rq_queued++;
+       if (rq->cmd_flags & REQ_META)
+               cfqq->meta_pending++;
 
        cfq_update_io_thinktime(cfqd, cfqq, cic);
        cfq_update_io_seektime(cfqd, cfqq, rq);
index 5cb51c5..e2f6790 100644 (file)
@@ -1146,17 +1146,17 @@ static int diskstats_show(struct seq_file *seqf, void *v)
                cpu = part_stat_lock();
                part_round_stats(cpu, hd);
                part_stat_unlock();
-               seq_printf(seqf, "%4d %7d %s %lu %lu %llu "
-                          "%u %lu %lu %llu %u %u %u %u\n",
+               seq_printf(seqf, "%4d %7d %s %lu %lu %lu "
+                          "%u %lu %lu %lu %u %u %u %u\n",
                           MAJOR(part_devt(hd)), MINOR(part_devt(hd)),
                           disk_name(gp, hd->partno, buf),
                           part_stat_read(hd, ios[READ]),
                           part_stat_read(hd, merges[READ]),
-                          (unsigned long long)part_stat_read(hd, sectors[READ]),
+                          part_stat_read(hd, sectors[READ]),
                           jiffies_to_msecs(part_stat_read(hd, ticks[READ])),
                           part_stat_read(hd, ios[WRITE]),
                           part_stat_read(hd, merges[WRITE]),
-                          (unsigned long long)part_stat_read(hd, sectors[WRITE]),
+                          part_stat_read(hd, sectors[WRITE]),
                           jiffies_to_msecs(part_stat_read(hd, ticks[WRITE])),
                           part_in_flight(hd),
                           jiffies_to_msecs(part_stat_read(hd, io_ticks)),
index ca3e6be..5987e0b 100644 (file)
@@ -468,6 +468,15 @@ config PATA_ICSIDE
          interface card.  This is not required for ICS partition support.
          If you are unsure, say N to this.
 
+config PATA_IMX
+       tristate "PATA support for Freescale iMX"
+       depends on ARCH_MXC
+       help
+         This option enables support for the PATA host available on Freescale
+          iMX SoCs.
+
+         If unsure, say N.
+
 config PATA_IT8213
        tristate "IT8213 PATA support (Experimental)"
        depends on PCI && EXPERIMENTAL
index 8ac64e1..9550d69 100644 (file)
@@ -48,6 +48,7 @@ obj-$(CONFIG_PATA_HPT37X)     += pata_hpt37x.o
 obj-$(CONFIG_PATA_HPT3X2N)     += pata_hpt3x2n.o
 obj-$(CONFIG_PATA_HPT3X3)      += pata_hpt3x3.o
 obj-$(CONFIG_PATA_ICSIDE)      += pata_icside.o
+obj-$(CONFIG_PATA_IMX)         += pata_imx.o
 obj-$(CONFIG_PATA_IT8213)      += pata_it8213.o
 obj-$(CONFIG_PATA_IT821X)      += pata_it821x.o
 obj-$(CONFIG_PATA_JMICRON)     += pata_jmicron.o
diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c
new file mode 100644 (file)
index 0000000..ca9d9ca
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Freescale iMX PATA driver
+ *
+ * Copyright (C) 2011 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * Based on pata_platform - Copyright (C) 2006 - 2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * TODO:
+ * - dmaengine support
+ * - check if timing stuff needed
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
+#include <linux/ata.h>
+#include <linux/libata.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#define DRV_NAME "pata_imx"
+
+#define PATA_IMX_ATA_CONTROL           0x24
+#define PATA_IMX_ATA_CTRL_FIFO_RST_B   (1<<7)
+#define PATA_IMX_ATA_CTRL_ATA_RST_B    (1<<6)
+#define PATA_IMX_ATA_CTRL_IORDY_EN     (1<<0)
+#define PATA_IMX_ATA_INT_EN            0x2C
+#define PATA_IMX_ATA_INTR_ATA_INTRQ2   (1<<3)
+#define PATA_IMX_DRIVE_DATA            0xA0
+#define PATA_IMX_DRIVE_CONTROL         0xD8
+
+struct pata_imx_priv {
+       struct clk *clk;
+       /* timings/interrupt/control regs */
+       u8 *host_regs;
+       u32 ata_ctl;
+};
+
+static int pata_imx_set_mode(struct ata_link *link, struct ata_device **unused)
+{
+       struct ata_device *dev;
+       struct ata_port *ap = link->ap;
+       struct pata_imx_priv *priv = ap->host->private_data;
+       u32 val;
+
+       ata_for_each_dev(dev, link, ENABLED) {
+               dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
+               dev->xfer_shift = ATA_SHIFT_PIO;
+               dev->flags |= ATA_DFLAG_PIO;
+
+               val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL);
+               if (ata_pio_need_iordy(dev))
+                       val |= PATA_IMX_ATA_CTRL_IORDY_EN;
+               else
+                       val &= ~PATA_IMX_ATA_CTRL_IORDY_EN;
+               __raw_writel(val, priv->host_regs + PATA_IMX_ATA_CONTROL);
+
+               ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+       }
+       return 0;
+}
+
+static struct scsi_host_template pata_imx_sht = {
+       ATA_PIO_SHT(DRV_NAME),
+};
+
+static struct ata_port_operations pata_imx_port_ops = {
+       .inherits               = &ata_sff_port_ops,
+       .sff_data_xfer          = ata_sff_data_xfer_noirq,
+       .cable_detect           = ata_cable_unknown,
+       .set_mode               = pata_imx_set_mode,
+};
+
+static void pata_imx_setup_port(struct ata_ioports *ioaddr)
+{
+       /* Fixup the port shift for platforms that need it */
+       ioaddr->data_addr       = ioaddr->cmd_addr + (ATA_REG_DATA    << 2);
+       ioaddr->error_addr      = ioaddr->cmd_addr + (ATA_REG_ERR     << 2);
+       ioaddr->feature_addr    = ioaddr->cmd_addr + (ATA_REG_FEATURE << 2);
+       ioaddr->nsect_addr      = ioaddr->cmd_addr + (ATA_REG_NSECT   << 2);
+       ioaddr->lbal_addr       = ioaddr->cmd_addr + (ATA_REG_LBAL    << 2);
+       ioaddr->lbam_addr       = ioaddr->cmd_addr + (ATA_REG_LBAM    << 2);
+       ioaddr->lbah_addr       = ioaddr->cmd_addr + (ATA_REG_LBAH    << 2);
+       ioaddr->device_addr     = ioaddr->cmd_addr + (ATA_REG_DEVICE  << 2);
+       ioaddr->status_addr     = ioaddr->cmd_addr + (ATA_REG_STATUS  << 2);
+       ioaddr->command_addr    = ioaddr->cmd_addr + (ATA_REG_CMD     << 2);
+}
+
+static int __devinit pata_imx_probe(struct platform_device *pdev)
+{
+       struct ata_host *host;
+       struct ata_port *ap;
+       struct pata_imx_priv *priv;
+       int irq = 0;
+       struct resource *io_res;
+
+       io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (io_res == NULL)
+               return -EINVAL;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0)
+               return -EINVAL;
+
+       priv = devm_kzalloc(&pdev->dev,
+                               sizeof(struct pata_imx_priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(priv->clk)) {
+               dev_err(&pdev->dev, "Failed to get clock\n");
+               return PTR_ERR(priv->clk);
+       }
+
+       clk_enable(priv->clk);
+
+       host = ata_host_alloc(&pdev->dev, 1);
+       if (!host)
+               goto free_priv;
+
+       host->private_data = priv;
+       ap = host->ports[0];
+
+       ap->ops = &pata_imx_port_ops;
+       ap->pio_mask = ATA_PIO0;
+       ap->flags |= ATA_FLAG_SLAVE_POSS;
+
+       priv->host_regs = devm_ioremap(&pdev->dev, io_res->start,
+               resource_size(io_res));
+       if (!priv->host_regs) {
+               dev_err(&pdev->dev, "failed to map IO/CTL base\n");
+               goto free_priv;
+       }
+
+       ap->ioaddr.cmd_addr = priv->host_regs + PATA_IMX_DRIVE_DATA;
+       ap->ioaddr.ctl_addr = priv->host_regs + PATA_IMX_DRIVE_CONTROL;
+
+       ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
+
+       pata_imx_setup_port(&ap->ioaddr);
+
+       ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
+               (unsigned long long)io_res->start + PATA_IMX_DRIVE_DATA,
+               (unsigned long long)io_res->start + PATA_IMX_DRIVE_CONTROL);
+
+       /* deassert resets */
+       __raw_writel(PATA_IMX_ATA_CTRL_FIFO_RST_B |
+                       PATA_IMX_ATA_CTRL_ATA_RST_B,
+                       priv->host_regs + PATA_IMX_ATA_CONTROL);
+       /* enable interrupts */
+       __raw_writel(PATA_IMX_ATA_INTR_ATA_INTRQ2,
+                       priv->host_regs + PATA_IMX_ATA_INT_EN);
+
+       /* activate */
+       return ata_host_activate(host, irq, ata_sff_interrupt, 0,
+                               &pata_imx_sht);
+
+free_priv:
+       clk_disable(priv->clk);
+       clk_put(priv->clk);
+       return -ENOMEM;
+}
+
+static int __devexit pata_imx_remove(struct platform_device *pdev)
+{
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       struct pata_imx_priv *priv = host->private_data;
+
+       ata_host_detach(host);
+
+       __raw_writel(0, priv->host_regs + PATA_IMX_ATA_INT_EN);
+
+       clk_disable(priv->clk);
+       clk_put(priv->clk);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int pata_imx_suspend(struct device *dev)
+{
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct pata_imx_priv *priv = host->private_data;
+       int ret;
+
+       ret = ata_host_suspend(host, PMSG_SUSPEND);
+       if (!ret) {
+               __raw_writel(0, priv->host_regs + PATA_IMX_ATA_INT_EN);
+               priv->ata_ctl =
+                       __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL);
+               clk_disable(priv->clk);
+       }
+
+       return ret;
+}
+
+static int pata_imx_resume(struct device *dev)
+{
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct pata_imx_priv *priv = host->private_data;
+
+       clk_enable(priv->clk);
+
+       __raw_writel(priv->ata_ctl, priv->host_regs + PATA_IMX_ATA_CONTROL);
+
+       __raw_writel(PATA_IMX_ATA_INTR_ATA_INTRQ2,
+                       priv->host_regs + PATA_IMX_ATA_INT_EN);
+
+       ata_host_resume(host);
+
+       return 0;
+}
+
+static const struct dev_pm_ops pata_imx_pm_ops = {
+       .suspend        = pata_imx_suspend,
+       .resume         = pata_imx_resume,
+};
+#endif
+
+static struct platform_driver pata_imx_driver = {
+       .probe          = pata_imx_probe,
+       .remove         = __devexit_p(pata_imx_remove),
+       .driver = {
+               .name           = DRV_NAME,
+               .owner          = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm             = &pata_imx_pm_ops,
+#endif
+       },
+};
+
+static int __init pata_imx_init(void)
+{
+       return platform_driver_register(&pata_imx_driver);
+}
+
+static void __exit pata_imx_exit(void)
+{
+       platform_driver_unregister(&pata_imx_driver);
+}
+module_init(pata_imx_init);
+module_exit(pata_imx_exit);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
+MODULE_DESCRIPTION("low-level driver for iMX PATA");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
index 65e4be6..8e9f504 100644 (file)
@@ -124,6 +124,17 @@ static const struct via_isa_bridge {
        { NULL }
 };
 
+static const struct dmi_system_id no_atapi_dma_dmi_table[] = {
+       {
+               .ident = "AVERATEC 3200",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "AVERATEC"),
+                       DMI_MATCH(DMI_BOARD_NAME, "3200"),
+               },
+       },
+       { }
+};
+
 struct via_port {
        u8 cached_device;
 };
@@ -355,6 +366,13 @@ static unsigned long via_mode_filter(struct ata_device *dev, unsigned long mask)
                        mask &= ~ ATA_MASK_UDMA;
                }
        }
+
+       if (dev->class == ATA_DEV_ATAPI &&
+           dmi_check_system(no_atapi_dma_dmi_table)) {
+               ata_dev_warn(dev, "controller locks up on ATAPI DMA, forcing PIO\n");
+               mask &= ATA_MASK_PIO;
+       }
+
        return mask;
 }
 
index 0a9a774..5c42374 100644 (file)
@@ -1329,7 +1329,7 @@ static int sata_dwc_port_start(struct ata_port *ap)
                        dev_err(ap->dev, "%s: dma_alloc_coherent failed\n",
                                 __func__);
                        err = -ENOMEM;
-                       goto CLEANUP;
+                       goto CLEANUP_ALLOC;
                }
        }
 
@@ -1349,15 +1349,13 @@ static int sata_dwc_port_start(struct ata_port *ap)
        /* Clear any error bits before libata starts issuing commands */
        clear_serror();
        ap->private_data = hsdevp;
+       dev_dbg(ap->dev, "%s: done\n", __func__);
+       return 0;
 
+CLEANUP_ALLOC:
+       kfree(hsdevp);
 CLEANUP:
-       if (err) {
-               sata_dwc_port_stop(ap);
-               dev_dbg(ap->dev, "%s: fail\n", __func__);
-       } else {
-               dev_dbg(ap->dev, "%s: done\n", __func__);
-       }
-
+       dev_dbg(ap->dev, "%s: fail. ap->id = %d\n", __func__, ap->print_id);
        return err;
 }
 
index 98c1d78..9dfb40b 100644 (file)
@@ -438,7 +438,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
        u8 status;
 
        if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) {
-               u32 serror;
+               u32 serror = 0xffffffff;
 
                /* SIEN doesn't mask SATA IRQs on some 3112s.  Those
                 * controllers continue to assert IRQ as long as
index cf7a0c7..65cd748 100644 (file)
@@ -397,6 +397,7 @@ static int remove_nodes(struct device *dev,
 
 static int release_nodes(struct device *dev, struct list_head *first,
                         struct list_head *end, unsigned long flags)
+       __releases(&dev->devres_lock)
 {
        LIST_HEAD(todo);
        int cnt;
index 33e1bed..a4760e0 100644 (file)
@@ -376,7 +376,7 @@ int devtmpfs_mount(const char *mntdir)
        return err;
 }
 
-static __initdata DECLARE_COMPLETION(setup_done);
+static DECLARE_COMPLETION(setup_done);
 
 static int handle(const char *name, mode_t mode, struct device *dev)
 {
index bbb03e6..06ed6b4 100644 (file)
@@ -521,11 +521,6 @@ static int _request_firmware(const struct firmware **firmware_p,
        if (!firmware_p)
                return -EINVAL;
 
-       if (WARN_ON(usermodehelper_is_disabled())) {
-               dev_err(device, "firmware: %s will not be loaded\n", name);
-               return -EBUSY;
-       }
-
        *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
        if (!firmware) {
                dev_err(device, "%s: kmalloc(struct firmware) failed\n",
@@ -539,6 +534,12 @@ static int _request_firmware(const struct firmware **firmware_p,
                return 0;
        }
 
+       if (WARN_ON(usermodehelper_is_disabled())) {
+               dev_err(device, "firmware: %s will not be loaded\n", name);
+               retval = -EBUSY;
+               goto out;
+       }
+
        if (uevent)
                dev_dbg(device, "firmware: requesting %s\n", name);
 
index 0cad9c7..99a5272 100644 (file)
@@ -33,7 +33,7 @@ EXPORT_SYMBOL_GPL(platform_bus);
 
 /**
  * arch_setup_pdev_archdata - Allow manipulation of archdata before its used
- * @dev: platform device
+ * @pdev: platform device
  *
  * This is called before platform_device_add() such that any pdev_archdata may
  * be setup before the platform_notifier is called.  So if a user needs to
index a846b2f..2c18d58 100644 (file)
@@ -19,7 +19,7 @@
 
 struct pm_clk_data {
        struct list_head clock_list;
-       struct mutex lock;
+       spinlock_t lock;
 };
 
 enum pce_status {
@@ -73,9 +73,9 @@ int pm_clk_add(struct device *dev, const char *con_id)
                }
        }
 
-       mutex_lock(&pcd->lock);
+       spin_lock_irq(&pcd->lock);
        list_add_tail(&ce->node, &pcd->clock_list);
-       mutex_unlock(&pcd->lock);
+       spin_unlock_irq(&pcd->lock);
        return 0;
 }
 
@@ -83,8 +83,8 @@ int pm_clk_add(struct device *dev, const char *con_id)
  * __pm_clk_remove - Destroy PM clock entry.
  * @ce: PM clock entry to destroy.
  *
- * This routine must be called under the mutex protecting the PM list of clocks
- * corresponding the the @ce's device.
+ * This routine must be called under the spinlock protecting the PM list of
+ * clocks corresponding the the @ce's device.
  */
 static void __pm_clk_remove(struct pm_clock_entry *ce)
 {
@@ -123,7 +123,7 @@ void pm_clk_remove(struct device *dev, const char *con_id)
        if (!pcd)
                return;
 
-       mutex_lock(&pcd->lock);
+       spin_lock_irq(&pcd->lock);
 
        list_for_each_entry(ce, &pcd->clock_list, node) {
                if (!con_id && !ce->con_id) {
@@ -137,7 +137,7 @@ void pm_clk_remove(struct device *dev, const char *con_id)
                }
        }
 
-       mutex_unlock(&pcd->lock);
+       spin_unlock_irq(&pcd->lock);
 }
 
 /**
@@ -158,7 +158,7 @@ int pm_clk_init(struct device *dev)
        }
 
        INIT_LIST_HEAD(&pcd->clock_list);
-       mutex_init(&pcd->lock);
+       spin_lock_init(&pcd->lock);
        dev->power.subsys_data = pcd;
        return 0;
 }
@@ -181,12 +181,12 @@ void pm_clk_destroy(struct device *dev)
 
        dev->power.subsys_data = NULL;
 
-       mutex_lock(&pcd->lock);
+       spin_lock_irq(&pcd->lock);
 
        list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node)
                __pm_clk_remove(ce);
 
-       mutex_unlock(&pcd->lock);
+       spin_unlock_irq(&pcd->lock);
 
        kfree(pcd);
 }
@@ -220,13 +220,14 @@ int pm_clk_suspend(struct device *dev)
 {
        struct pm_clk_data *pcd = __to_pcd(dev);
        struct pm_clock_entry *ce;
+       unsigned long flags;
 
        dev_dbg(dev, "%s()\n", __func__);
 
        if (!pcd)
                return 0;
 
-       mutex_lock(&pcd->lock);
+       spin_lock_irqsave(&pcd->lock, flags);
 
        list_for_each_entry_reverse(ce, &pcd->clock_list, node) {
                if (ce->status == PCE_STATUS_NONE)
@@ -238,7 +239,7 @@ int pm_clk_suspend(struct device *dev)
                }
        }
 
-       mutex_unlock(&pcd->lock);
+       spin_unlock_irqrestore(&pcd->lock, flags);
 
        return 0;
 }
@@ -251,13 +252,14 @@ int pm_clk_resume(struct device *dev)
 {
        struct pm_clk_data *pcd = __to_pcd(dev);
        struct pm_clock_entry *ce;
+       unsigned long flags;
 
        dev_dbg(dev, "%s()\n", __func__);
 
        if (!pcd)
                return 0;
 
-       mutex_lock(&pcd->lock);
+       spin_lock_irqsave(&pcd->lock, flags);
 
        list_for_each_entry(ce, &pcd->clock_list, node) {
                if (ce->status == PCE_STATUS_NONE)
@@ -269,7 +271,7 @@ int pm_clk_resume(struct device *dev)
                }
        }
 
-       mutex_unlock(&pcd->lock);
+       spin_unlock_irqrestore(&pcd->lock, flags);
 
        return 0;
 }
@@ -344,6 +346,7 @@ int pm_clk_suspend(struct device *dev)
 {
        struct pm_clk_data *pcd = __to_pcd(dev);
        struct pm_clock_entry *ce;
+       unsigned long flags;
 
        dev_dbg(dev, "%s()\n", __func__);
 
@@ -351,12 +354,12 @@ int pm_clk_suspend(struct device *dev)
        if (!pcd || !dev->driver)
                return 0;
 
-       mutex_lock(&pcd->lock);
+       spin_lock_irqsave(&pcd->lock, flags);
 
        list_for_each_entry_reverse(ce, &pcd->clock_list, node)
                clk_disable(ce->clk);
 
-       mutex_unlock(&pcd->lock);
+       spin_unlock_irqrestore(&pcd->lock, flags);
 
        return 0;
 }
@@ -369,6 +372,7 @@ int pm_clk_resume(struct device *dev)
 {
        struct pm_clk_data *pcd = __to_pcd(dev);
        struct pm_clock_entry *ce;
+       unsigned long flags;
 
        dev_dbg(dev, "%s()\n", __func__);
 
@@ -376,12 +380,12 @@ int pm_clk_resume(struct device *dev)
        if (!pcd || !dev->driver)
                return 0;
 
-       mutex_lock(&pcd->lock);
+       spin_lock_irqsave(&pcd->lock, flags);
 
        list_for_each_entry(ce, &pcd->clock_list, node)
                clk_enable(ce->clk);
 
-       mutex_unlock(&pcd->lock);
+       spin_unlock_irqrestore(&pcd->lock, flags);
 
        return 0;
 }
index e18566a..1c37457 100644 (file)
@@ -460,6 +460,21 @@ static int pm_genpd_runtime_resume(struct device *dev)
        return 0;
 }
 
+/**
+ * pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
+ */
+void pm_genpd_poweroff_unused(void)
+{
+       struct generic_pm_domain *genpd;
+
+       mutex_lock(&gpd_list_lock);
+
+       list_for_each_entry(genpd, &gpd_list, gpd_list_node)
+               genpd_queue_power_off_work(genpd);
+
+       mutex_unlock(&gpd_list_lock);
+}
+
 #else
 
 static inline void genpd_power_off_work_fn(struct work_struct *work) {}
@@ -1255,18 +1270,3 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
        list_add(&genpd->gpd_list_node, &gpd_list);
        mutex_unlock(&gpd_list_lock);
 }
-
-/**
- * pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
- */
-void pm_genpd_poweroff_unused(void)
-{
-       struct generic_pm_domain *genpd;
-
-       mutex_lock(&gpd_list_lock);
-
-       list_for_each_entry(genpd, &gpd_list, gpd_list_node)
-               genpd_queue_power_off_work(genpd);
-
-       mutex_unlock(&gpd_list_lock);
-}
index c2231ff..c4f7a45 100644 (file)
@@ -113,3 +113,4 @@ struct regmap *regmap_init_i2c(struct i2c_client *i2c,
 }
 EXPORT_SYMBOL_GPL(regmap_init_i2c);
 
+MODULE_LICENSE("GPL");
index 4deba06..f839694 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 static int regmap_spi_write(struct device *dev, const void *data, size_t count)
 {
@@ -70,3 +71,5 @@ struct regmap *regmap_init_spi(struct spi_device *spi,
        return regmap_init(&spi->dev, &regmap_spi, config);
 }
 EXPORT_SYMBOL_GPL(regmap_init_spi);
+
+MODULE_LICENSE("GPL");
index cf3565c..20663f8 100644 (file)
@@ -168,13 +168,11 @@ struct regmap *regmap_init(struct device *dev,
        map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL);
        if (map->work_buf == NULL) {
                ret = -ENOMEM;
-               goto err_bus;
+               goto err_map;
        }
 
        return map;
 
-err_bus:
-       module_put(map->bus->owner);
 err_map:
        kfree(map);
 err:
@@ -188,7 +186,6 @@ EXPORT_SYMBOL_GPL(regmap_init);
 void regmap_exit(struct regmap *map)
 {
        kfree(map->work_buf);
-       module_put(map->bus->owner);
        kfree(map);
 }
 EXPORT_SYMBOL_GPL(regmap_exit);
@@ -317,7 +314,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
                u8[0] |= map->bus->read_flag_mask;
 
        ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
-                            val, map->format.val_bytes);
+                            val, val_len);
        if (ret != 0)
                return ret;
 
index 873e2e4..73b7b1a 100644 (file)
@@ -15,6 +15,7 @@ MODULE_LICENSE("GPL");
 static int bcma_bus_match(struct device *dev, struct device_driver *drv);
 static int bcma_device_probe(struct device *dev);
 static int bcma_device_remove(struct device *dev);
+static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
 
 static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -49,6 +50,7 @@ static struct bus_type bcma_bus_type = {
        .match          = bcma_bus_match,
        .probe          = bcma_device_probe,
        .remove         = bcma_device_remove,
+       .uevent         = bcma_device_uevent,
        .dev_attrs      = bcma_device_attrs,
 };
 
@@ -227,6 +229,16 @@ static int bcma_device_remove(struct device *dev)
        return 0;
 }
 
+static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+
+       return add_uevent_var(env,
+                             "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
+                             core->id.manuf, core->id.id,
+                             core->id.rev, core->id.class);
+}
+
 static int __init bcma_modinit(void)
 {
        int err;
index 717d6e4..6f07ec1 100644 (file)
@@ -256,6 +256,21 @@ config BLK_DEV_LOOP
 
          Most users will answer N here.
 
+config BLK_DEV_LOOP_MIN_COUNT
+       int "Number of loop devices to pre-create at init time"
+       depends on BLK_DEV_LOOP
+       default 8
+       help
+         Static number of loop devices to be unconditionally pre-created
+         at init time.
+
+         This default value can be overwritten on the kernel command
+         line or with module-parameter loop.max_loop.
+
+         The historic default is 8. If a late 2011 version of losetup(8)
+         is used, it can be set to 0, since needed loop devices can be
+         dynamically allocated with the /dev/loop-control interface.
+
 config BLK_DEV_CRYPTOLOOP
        tristate "Cryptoloop Support"
        select CRYPTO
@@ -471,7 +486,7 @@ config XEN_BLKDEV_FRONTEND
          in another domain which drives the actual block device.
 
 config XEN_BLKDEV_BACKEND
-       tristate "Block-device backend driver"
+       tristate "Xen block-device backend driver"
        depends on XEN_BACKEND
        help
          The block-device backend driver allows the kernel to export its
index 515bcd9..0feab26 100644 (file)
@@ -1829,10 +1829,10 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
 
        /* silently ignore cpu mask on UP kernel */
        if (nr_cpu_ids > 1 && sc.cpu_mask[0] != 0) {
-               err = __bitmap_parse(sc.cpu_mask, 32, 0,
+               err = bitmap_parse(sc.cpu_mask, 32,
                                cpumask_bits(new_cpu_mask), nr_cpu_ids);
                if (err) {
-                       dev_warn(DEV, "__bitmap_parse() failed with %d\n", err);
+                       dev_warn(DEV, "bitmap_parse() failed with %d\n", err);
                        retcode = ERR_CPU_MASK_PARSE;
                        goto fail;
                }
index 76c8da7..4720c7a 100644 (file)
 #include <linux/kthread.h>
 #include <linux/splice.h>
 #include <linux/sysfs.h>
-
+#include <linux/miscdevice.h>
 #include <asm/uaccess.h>
 
-static LIST_HEAD(loop_devices);
-static DEFINE_MUTEX(loop_devices_mutex);
+static DEFINE_IDR(loop_index_idr);
+static DEFINE_MUTEX(loop_index_mutex);
 
 static int max_part;
 static int part_shift;
@@ -722,17 +722,10 @@ static inline int is_loop_device(struct file *file)
 static ssize_t loop_attr_show(struct device *dev, char *page,
                              ssize_t (*callback)(struct loop_device *, char *))
 {
-       struct loop_device *l, *lo = NULL;
-
-       mutex_lock(&loop_devices_mutex);
-       list_for_each_entry(l, &loop_devices, lo_list)
-               if (disk_to_dev(l->lo_disk) == dev) {
-                       lo = l;
-                       break;
-               }
-       mutex_unlock(&loop_devices_mutex);
+       struct gendisk *disk = dev_to_disk(dev);
+       struct loop_device *lo = disk->private_data;
 
-       return lo ? callback(lo, page) : -EIO;
+       return callback(lo, page);
 }
 
 #define LOOP_ATTR_RO(_name)                                            \
@@ -750,10 +743,10 @@ static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf)
        ssize_t ret;
        char *p = NULL;
 
-       mutex_lock(&lo->lo_ctl_mutex);
+       spin_lock_irq(&lo->lo_lock);
        if (lo->lo_backing_file)
                p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1);
-       mutex_unlock(&lo->lo_ctl_mutex);
+       spin_unlock_irq(&lo->lo_lock);
 
        if (IS_ERR_OR_NULL(p))
                ret = PTR_ERR(p);
@@ -1007,7 +1000,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 
        kthread_stop(lo->lo_thread);
 
+       spin_lock_irq(&lo->lo_lock);
        lo->lo_backing_file = NULL;
+       spin_unlock_irq(&lo->lo_lock);
 
        loop_release_xfer(lo);
        lo->transfer = NULL;
@@ -1485,13 +1480,22 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
 
 static int lo_open(struct block_device *bdev, fmode_t mode)
 {
-       struct loop_device *lo = bdev->bd_disk->private_data;
+       struct loop_device *lo;
+       int err = 0;
+
+       mutex_lock(&loop_index_mutex);
+       lo = bdev->bd_disk->private_data;
+       if (!lo) {
+               err = -ENXIO;
+               goto out;
+       }
 
        mutex_lock(&lo->lo_ctl_mutex);
        lo->lo_refcnt++;
        mutex_unlock(&lo->lo_ctl_mutex);
-
-       return 0;
+out:
+       mutex_unlock(&loop_index_mutex);
+       return err;
 }
 
 static int lo_release(struct gendisk *disk, fmode_t mode)
@@ -1557,40 +1561,71 @@ int loop_register_transfer(struct loop_func_table *funcs)
        return 0;
 }
 
+static int unregister_transfer_cb(int id, void *ptr, void *data)
+{
+       struct loop_device *lo = ptr;
+       struct loop_func_table *xfer = data;
+
+       mutex_lock(&lo->lo_ctl_mutex);
+       if (lo->lo_encryption == xfer)
+               loop_release_xfer(lo);
+       mutex_unlock(&lo->lo_ctl_mutex);
+       return 0;
+}
+
 int loop_unregister_transfer(int number)
 {
        unsigned int n = number;
-       struct loop_device *lo;
        struct loop_func_table *xfer;
 
        if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL)
                return -EINVAL;
 
        xfer_funcs[n] = NULL;
-
-       list_for_each_entry(lo, &loop_devices, lo_list) {
-               mutex_lock(&lo->lo_ctl_mutex);
-
-               if (lo->lo_encryption == xfer)
-                       loop_release_xfer(lo);
-
-               mutex_unlock(&lo->lo_ctl_mutex);
-       }
-
+       idr_for_each(&loop_index_idr, &unregister_transfer_cb, xfer);
        return 0;
 }
 
 EXPORT_SYMBOL(loop_register_transfer);
 EXPORT_SYMBOL(loop_unregister_transfer);
 
-static struct loop_device *loop_alloc(int i)
+static int loop_add(struct loop_device **l, int i)
 {
        struct loop_device *lo;
        struct gendisk *disk;
+       int err;
 
        lo = kzalloc(sizeof(*lo), GFP_KERNEL);
-       if (!lo)
+       if (!lo) {
+               err = -ENOMEM;
                goto out;
+       }
+
+       err = idr_pre_get(&loop_index_idr, GFP_KERNEL);
+       if (err < 0)
+               goto out_free_dev;
+
+       if (i >= 0) {
+               int m;
+
+               /* create specific i in the index */
+               err = idr_get_new_above(&loop_index_idr, lo, i, &m);
+               if (err >= 0 && i != m) {
+                       idr_remove(&loop_index_idr, m);
+                       err = -EEXIST;
+               }
+       } else if (i == -1) {
+               int m;
+
+               /* get next free nr */
+               err = idr_get_new(&loop_index_idr, lo, &m);
+               if (err >= 0)
+                       i = m;
+       } else {
+               err = -EINVAL;
+       }
+       if (err < 0)
+               goto out_free_dev;
 
        lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
        if (!lo->lo_queue)
@@ -1611,81 +1646,158 @@ static struct loop_device *loop_alloc(int i)
        disk->private_data      = lo;
        disk->queue             = lo->lo_queue;
        sprintf(disk->disk_name, "loop%d", i);
-       return lo;
+       add_disk(disk);
+       *l = lo;
+       return lo->lo_number;
 
 out_free_queue:
        blk_cleanup_queue(lo->lo_queue);
 out_free_dev:
        kfree(lo);
 out:
-       return NULL;
+       return err;
 }
 
-static void loop_free(struct loop_device *lo)
+static void loop_remove(struct loop_device *lo)
 {
+       del_gendisk(lo->lo_disk);
        blk_cleanup_queue(lo->lo_queue);
        put_disk(lo->lo_disk);
-       list_del(&lo->lo_list);
        kfree(lo);
 }
 
-static struct loop_device *loop_init_one(int i)
+static int find_free_cb(int id, void *ptr, void *data)
+{
+       struct loop_device *lo = ptr;
+       struct loop_device **l = data;
+
+       if (lo->lo_state == Lo_unbound) {
+               *l = lo;
+               return 1;
+       }
+       return 0;
+}
+
+static int loop_lookup(struct loop_device **l, int i)
 {
        struct loop_device *lo;
+       int ret = -ENODEV;
 
-       list_for_each_entry(lo, &loop_devices, lo_list) {
-               if (lo->lo_number == i)
-                       return lo;
+       if (i < 0) {
+               int err;
+
+               err = idr_for_each(&loop_index_idr, &find_free_cb, &lo);
+               if (err == 1) {
+                       *l = lo;
+                       ret = lo->lo_number;
+               }
+               goto out;
        }
 
-       lo = loop_alloc(i);
+       /* lookup and return a specific i */
+       lo = idr_find(&loop_index_idr, i);
        if (lo) {
-               add_disk(lo->lo_disk);
-               list_add_tail(&lo->lo_list, &loop_devices);
+               *l = lo;
+               ret = lo->lo_number;
        }
-       return lo;
-}
-
-static void loop_del_one(struct loop_device *lo)
-{
-       del_gendisk(lo->lo_disk);
-       loop_free(lo);
+out:
+       return ret;
 }
 
 static struct kobject *loop_probe(dev_t dev, int *part, void *data)
 {
        struct loop_device *lo;
        struct kobject *kobj;
+       int err;
 
-       mutex_lock(&loop_devices_mutex);
-       lo = loop_init_one(MINOR(dev) >> part_shift);
-       kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM);
-       mutex_unlock(&loop_devices_mutex);
+       mutex_lock(&loop_index_mutex);
+       err = loop_lookup(&lo, MINOR(dev) >> part_shift);
+       if (err < 0)
+               err = loop_add(&lo, MINOR(dev) >> part_shift);
+       if (err < 0)
+               kobj = ERR_PTR(err);
+       else
+               kobj = get_disk(lo->lo_disk);
+       mutex_unlock(&loop_index_mutex);
 
        *part = 0;
        return kobj;
 }
 
+static long loop_control_ioctl(struct file *file, unsigned int cmd,
+                              unsigned long parm)
+{
+       struct loop_device *lo;
+       int ret = -ENOSYS;
+
+       mutex_lock(&loop_index_mutex);
+       switch (cmd) {
+       case LOOP_CTL_ADD:
+               ret = loop_lookup(&lo, parm);
+               if (ret >= 0) {
+                       ret = -EEXIST;
+                       break;
+               }
+               ret = loop_add(&lo, parm);
+               break;
+       case LOOP_CTL_REMOVE:
+               ret = loop_lookup(&lo, parm);
+               if (ret < 0)
+                       break;
+               mutex_lock(&lo->lo_ctl_mutex);
+               if (lo->lo_state != Lo_unbound) {
+                       ret = -EBUSY;
+                       mutex_unlock(&lo->lo_ctl_mutex);
+                       break;
+               }
+               if (lo->lo_refcnt > 0) {
+                       ret = -EBUSY;
+                       mutex_unlock(&lo->lo_ctl_mutex);
+                       break;
+               }
+               lo->lo_disk->private_data = NULL;
+               mutex_unlock(&lo->lo_ctl_mutex);
+               idr_remove(&loop_index_idr, lo->lo_number);
+               loop_remove(lo);
+               break;
+       case LOOP_CTL_GET_FREE:
+               ret = loop_lookup(&lo, -1);
+               if (ret >= 0)
+                       break;
+               ret = loop_add(&lo, -1);
+       }
+       mutex_unlock(&loop_index_mutex);
+
+       return ret;
+}
+
+static const struct file_operations loop_ctl_fops = {
+       .open           = nonseekable_open,
+       .unlocked_ioctl = loop_control_ioctl,
+       .compat_ioctl   = loop_control_ioctl,
+       .owner          = THIS_MODULE,
+       .llseek         = noop_llseek,
+};
+
+static struct miscdevice loop_misc = {
+       .minor          = LOOP_CTRL_MINOR,
+       .name           = "loop-control",
+       .fops           = &loop_ctl_fops,
+};
+
+MODULE_ALIAS_MISCDEV(LOOP_CTRL_MINOR);
+MODULE_ALIAS("devname:loop-control");
+
 static int __init loop_init(void)
 {
        int i, nr;
        unsigned long range;
-       struct loop_device *lo, *next;
+       struct loop_device *lo;
+       int err;
 
-       /*
-        * loop module now has a feature to instantiate underlying device
-        * structure on-demand, provided that there is an access dev node.
-        * However, this will not work well with user space tool that doesn't
-        * know about such "feature".  In order to not break any existing
-        * tool, we do the following:
-        *
-        * (1) if max_loop is specified, create that many upfront, and this
-        *     also becomes a hard limit.
-        * (2) if max_loop is not specified, create 8 loop device on module
-        *     load, user can further extend loop device by create dev node
-        *     themselves and have kernel automatically instantiate actual
-        *     device on-demand.
-        */
+       err = misc_register(&loop_misc);
+       if (err < 0)
+               return err;
 
        part_shift = 0;
        if (max_part > 0) {
@@ -1708,57 +1820,60 @@ static int __init loop_init(void)
        if (max_loop > 1UL << (MINORBITS - part_shift))
                return -EINVAL;
 
+       /*
+        * If max_loop is specified, create that many devices upfront.
+        * This also becomes a hard limit. If max_loop is not specified,
+        * create CONFIG_BLK_DEV_LOOP_MIN_COUNT loop devices at module
+        * init time. Loop devices can be requested on-demand with the
+        * /dev/loop-control interface, or be instantiated by accessing
+        * a 'dead' device node.
+        */
        if (max_loop) {
                nr = max_loop;
                range = max_loop << part_shift;
        } else {
-               nr = 8;
+               nr = CONFIG_BLK_DEV_LOOP_MIN_COUNT;
                range = 1UL << MINORBITS;
        }
 
        if (register_blkdev(LOOP_MAJOR, "loop"))
                return -EIO;
 
-       for (i = 0; i < nr; i++) {
-               lo = loop_alloc(i);
-               if (!lo)
-                       goto Enomem;
-               list_add_tail(&lo->lo_list, &loop_devices);
-       }
-
-       /* point of no return */
-
-       list_for_each_entry(lo, &loop_devices, lo_list)
-               add_disk(lo->lo_disk);
-
        blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
                                  THIS_MODULE, loop_probe, NULL, NULL);
 
+       /* pre-create number of devices given by config or max_loop */
+       mutex_lock(&loop_index_mutex);
+       for (i = 0; i < nr; i++)
+               loop_add(&lo, i);
+       mutex_unlock(&loop_index_mutex);
+
        printk(KERN_INFO "loop: module loaded\n");
        return 0;
+}
 
-Enomem:
-       printk(KERN_INFO "loop: out of memory\n");
-
-       list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
-               loop_free(lo);
+static int loop_exit_cb(int id, void *ptr, void *data)
+{
+       struct loop_device *lo = ptr;
 
-       unregister_blkdev(LOOP_MAJOR, "loop");
-       return -ENOMEM;
+       loop_remove(lo);
+       return 0;
 }
 
 static void __exit loop_exit(void)
 {
        unsigned long range;
-       struct loop_device *lo, *next;
 
        range = max_loop ? max_loop << part_shift : 1UL << MINORBITS;
 
-       list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
-               loop_del_one(lo);
+       idr_for_each(&loop_index_idr, &loop_exit_cb, NULL);
+       idr_remove_all(&loop_index_idr);
+       idr_destroy(&loop_index_idr);
 
        blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
        unregister_blkdev(LOOP_MAJOR, "loop");
+
+       misc_deregister(&loop_misc);
 }
 
 module_init(loop_init);
index 773bfa7..ae3e167 100644 (file)
@@ -1184,6 +1184,7 @@ static struct of_device_id swim3_match[] =
        {
        .compatible     = "swim3"
        },
+       { /* end of list */ }
 };
 
 static struct macio_driver swim3_driver =
index b536a9c..9ea8c25 100644 (file)
@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock);
 #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
 #define EMULATED_HD_DISK_MINOR_OFFSET (0)
 #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256)
-#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16))
-#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4)
+#define EMULATED_SD_DISK_MINOR_OFFSET (0)
+#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256)
 
 #define DEV_NAME       "xvd"   /* name in /dev */
 
@@ -529,7 +529,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
                minor = BLKIF_MINOR_EXT(info->vdevice);
                nr_parts = PARTS_PER_EXT_DISK;
                offset = minor / nr_parts;
-               if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4)
+               if (xen_hvm_domain() && offset < EMULATED_HD_DISK_NAME_OFFSET + 4)
                        printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with "
                                        "emulated IDE disks,\n\t choose an xvd device name"
                                        "from xvde on\n", info->vdevice);
index a585473..db7cb81 100644 (file)
@@ -63,6 +63,7 @@ static struct usb_device_id ath3k_table[] = {
        /* Atheros AR3011 with sflash firmware*/
        { USB_DEVICE(0x0CF3, 0x3002) },
        { USB_DEVICE(0x13d3, 0x3304) },
+       { USB_DEVICE(0x0930, 0x0215) },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03F0, 0x311D) },
index 91d13a9..3ef4760 100644 (file)
@@ -106,6 +106,7 @@ static struct usb_device_id blacklist_table[] = {
        /* Atheros 3011 with sflash firmware */
        { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
@@ -256,7 +257,9 @@ static void btusb_intr_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               if (err != -EPERM)
+               /* -EPERM: urb is being killed;
+                * -ENODEV: device got disconnected */
+               if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
@@ -341,7 +344,9 @@ static void btusb_bulk_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               if (err != -EPERM)
+               /* -EPERM: urb is being killed;
+                * -ENODEV: device got disconnected */
+               if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
@@ -431,7 +436,9 @@ static void btusb_isoc_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               if (err != -EPERM)
+               /* -EPERM: urb is being killed;
+                * -ENODEV: device got disconnected */
+               if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
index 75fb965..f997c27 100644 (file)
@@ -1929,11 +1929,17 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s,
                goto out;
 
        s->manufact.len = buf[0] << 8 | buf[1];
-       if (s->manufact.len < 0 || s->manufact.len > 2048) {
+       if (s->manufact.len < 0) {
                cdinfo(CD_WARNING, "Received invalid manufacture info length"
                                   " (%d)\n", s->manufact.len);
                ret = -EIO;
        } else {
+               if (s->manufact.len > 2048) {
+                       cdinfo(CD_WARNING, "Received invalid manufacture info "
+                                       "length (%d): truncating to 2048\n",
+                                       s->manufact.len);
+                       s->manufact.len = 2048;
+               }
                memcpy(s->manufact.value, &buf[4], s->manufact.len);
        }
 
index b6f8a65..8eca55d 100644 (file)
@@ -379,9 +379,8 @@ static int __init smd_pkt_init(void)
        for (i = 0; i < NUM_SMD_PKT_PORTS; ++i) {
                smd_pkt_devp[i] = kzalloc(sizeof(struct smd_pkt_dev),
                                          GFP_KERNEL);
-               if (IS_ERR(smd_pkt_devp[i])) {
-                       r = PTR_ERR(smd_pkt_devp[i]);
-                       pr_err("kmalloc() failed %d\n", r);
+               if (!smd_pkt_devp[i]) {
+                       pr_err("kmalloc() failed\n");
                        goto clean_cdevs;
                }
 
index dc7c033..32a77be 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/sh_timer.h>
@@ -150,13 +151,13 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 
 static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
 {
-       int ret;
+       int k, ret;
 
        /* enable clock */
        ret = clk_enable(p->clk);
        if (ret) {
                dev_err(&p->pdev->dev, "cannot enable clock\n");
-               return ret;
+               goto err0;
        }
 
        /* make sure channel is disabled */
@@ -174,9 +175,38 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
        sh_cmt_write(p, CMCOR, 0xffffffff);
        sh_cmt_write(p, CMCNT, 0);
 
+       /*
+        * According to the sh73a0 user's manual, as CMCNT can be operated
+        * only by the RCLK (Pseudo 32 KHz), there's one restriction on
+        * modifying CMCNT register; two RCLK cycles are necessary before
+        * this register is either read or any modification of the value
+        * it holds is reflected in the LSI's actual operation.
+        *
+        * While at it, we're supposed to clear out the CMCNT as of this
+        * moment, so make sure it's processed properly here.  This will
+        * take RCLKx2 at maximum.
+        */
+       for (k = 0; k < 100; k++) {
+               if (!sh_cmt_read(p, CMCNT))
+                       break;
+               udelay(1);
+       }
+
+       if (sh_cmt_read(p, CMCNT)) {
+               dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
+               ret = -ETIMEDOUT;
+               goto err1;
+       }
+
        /* enable channel */
        sh_cmt_start_stop_ch(p, 1);
        return 0;
+ err1:
+       /* stop clock */
+       clk_disable(p->clk);
+
+ err0:
+       return ret;
 }
 
 static void sh_cmt_disable(struct sh_cmt_priv *p)
index cd3a7c7..467e4dc 100644 (file)
@@ -174,8 +174,10 @@ struct d40_base;
  * @tasklet: Tasklet that gets scheduled from interrupt context to complete a
  * transfer and call client callback.
  * @client: Cliented owned descriptor list.
+ * @pending_queue: Submitted jobs, to be issued by issue_pending()
  * @active: Active descriptor.
  * @queue: Queued jobs.
+ * @prepare_queue: Prepared jobs.
  * @dma_cfg: The client configuration of this dma channel.
  * @configured: whether the dma_cfg configuration is valid
  * @base: Pointer to the device instance struct.
@@ -203,6 +205,7 @@ struct d40_chan {
        struct list_head                 pending_queue;
        struct list_head                 active;
        struct list_head                 queue;
+       struct list_head                 prepare_queue;
        struct stedma40_chan_cfg         dma_cfg;
        bool                             configured;
        struct d40_base                 *base;
@@ -477,7 +480,6 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c)
 
                list_for_each_entry_safe(d, _d, &d40c->client, node)
                        if (async_tx_test_ack(&d->txd)) {
-                               d40_pool_lli_free(d40c, d);
                                d40_desc_remove(d);
                                desc = d;
                                memset(desc, 0, sizeof(*desc));
@@ -644,8 +646,11 @@ static struct d40_desc *d40_first_active_get(struct d40_chan *d40c)
        return d;
 }
 
+/* remove desc from current queue and add it to the pending_queue */
 static void d40_desc_queue(struct d40_chan *d40c, struct d40_desc *desc)
 {
+       d40_desc_remove(desc);
+       desc->is_in_client_list = false;
        list_add_tail(&desc->node, &d40c->pending_queue);
 }
 
@@ -803,6 +808,7 @@ done:
 static void d40_term_all(struct d40_chan *d40c)
 {
        struct d40_desc *d40d;
+       struct d40_desc *_d;
 
        /* Release active descriptors */
        while ((d40d = d40_first_active_get(d40c))) {
@@ -822,6 +828,21 @@ static void d40_term_all(struct d40_chan *d40c)
                d40_desc_free(d40c, d40d);
        }
 
+       /* Release client owned descriptors */
+       if (!list_empty(&d40c->client))
+               list_for_each_entry_safe(d40d, _d, &d40c->client, node) {
+                       d40_desc_remove(d40d);
+                       d40_desc_free(d40c, d40d);
+               }
+
+       /* Release descriptors in prepare queue */
+       if (!list_empty(&d40c->prepare_queue))
+               list_for_each_entry_safe(d40d, _d,
+                                        &d40c->prepare_queue, node) {
+                       d40_desc_remove(d40d);
+                       d40_desc_free(d40c, d40d);
+               }
+
        d40c->pending_tx = 0;
        d40c->busy = false;
 }
@@ -1208,7 +1229,6 @@ static void dma_tasklet(unsigned long data)
 
        if (!d40d->cyclic) {
                if (async_tx_test_ack(&d40d->txd)) {
-                       d40_pool_lli_free(d40c, d40d);
                        d40_desc_remove(d40d);
                        d40_desc_free(d40c, d40d);
                } else {
@@ -1595,21 +1615,10 @@ static int d40_free_dma(struct d40_chan *d40c)
        u32 event;
        struct d40_phy_res *phy = d40c->phy_chan;
        bool is_src;
-       struct d40_desc *d;
-       struct d40_desc *_d;
-
 
        /* Terminate all queued and active transfers */
        d40_term_all(d40c);
 
-       /* Release client owned descriptors */
-       if (!list_empty(&d40c->client))
-               list_for_each_entry_safe(d, _d, &d40c->client, node) {
-                       d40_pool_lli_free(d40c, d);
-                       d40_desc_remove(d);
-                       d40_desc_free(d40c, d);
-               }
-
        if (phy == NULL) {
                chan_err(d40c, "phy == null\n");
                return -EINVAL;
@@ -1911,6 +1920,12 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
                goto err;
        }
 
+       /*
+        * add descriptor to the prepare queue in order to be able
+        * to free them later in terminate_all
+        */
+       list_add_tail(&desc->node, &chan->prepare_queue);
+
        spin_unlock_irqrestore(&chan->lock, flags);
 
        return &desc->txd;
@@ -2400,6 +2415,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
                INIT_LIST_HEAD(&d40c->queue);
                INIT_LIST_HEAD(&d40c->pending_queue);
                INIT_LIST_HEAD(&d40c->client);
+               INIT_LIST_HEAD(&d40c->prepare_queue);
 
                tasklet_init(&d40c->tasklet, dma_tasklet,
                             (unsigned long) d40c);
index 04f1e7c..f6cf448 100644 (file)
@@ -1670,7 +1670,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,
        char *type, *optype, *err, *msg;
        unsigned long error = m->status & 0x1ff0000l;
        u32 optypenum = (m->status >> 4) & 0x07;
-       u32 core_err_cnt = (m->status >> 38) && 0x7fff;
+       u32 core_err_cnt = (m->status >> 38) & 0x7fff;
        u32 dimm = (m->misc >> 16) & 0x3;
        u32 channel = (m->misc >> 18) & 0x3;
        u32 syndrome = m->misc >> 32;
index e6ad3bb..4799393 100644 (file)
@@ -216,15 +216,33 @@ struct inbound_phy_packet_event {
        struct fw_cdev_event_phy_packet phy_packet;
 };
 
-static inline void __user *u64_to_uptr(__u64 value)
+#ifdef CONFIG_COMPAT
+static void __user *u64_to_uptr(u64 value)
+{
+       if (is_compat_task())
+               return compat_ptr(value);
+       else
+               return (void __user *)(unsigned long)value;
+}
+
+static u64 uptr_to_u64(void __user *ptr)
+{
+       if (is_compat_task())
+               return ptr_to_compat(ptr);
+       else
+               return (u64)(unsigned long)ptr;
+}
+#else
+static inline void __user *u64_to_uptr(u64 value)
 {
        return (void __user *)(unsigned long)value;
 }
 
-static inline __u64 uptr_to_u64(void __user *ptr)
+static inline u64 uptr_to_u64(void __user *ptr)
 {
-       return (__u64)(unsigned long)ptr;
+       return (u64)(unsigned long)ptr;
 }
+#endif /* CONFIG_COMPAT */
 
 static int fw_device_op_open(struct inode *inode, struct file *file)
 {
index 8ba7f79..f3b890d 100644 (file)
@@ -455,15 +455,20 @@ static struct device_attribute fw_device_attributes[] = {
 static int read_rom(struct fw_device *device,
                    int generation, int index, u32 *data)
 {
-       int rcode;
+       u64 offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
+       int i, rcode;
 
        /* device->node_id, accessed below, must not be older than generation */
        smp_rmb();
 
-       rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
-                       device->node_id, generation, device->max_speed,
-                       (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
-                       data, 4);
+       for (i = 10; i < 100; i += 10) {
+               rcode = fw_run_transaction(device->card,
+                               TCODE_READ_QUADLET_REQUEST, device->node_id,
+                               generation, device->max_speed, offset, data, 4);
+               if (rcode != RCODE_BUSY)
+                       break;
+               msleep(i);
+       }
        be32_to_cpus(data);
 
        return rcode;
index bcf792f..57cd3a4 100644 (file)
@@ -2179,8 +2179,13 @@ static int ohci_enable(struct fw_card *card,
                        ohci_driver_name, ohci)) {
                fw_error("Failed to allocate interrupt %d.\n", dev->irq);
                pci_disable_msi(dev);
-               dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-                                 ohci->config_rom, ohci->config_rom_bus);
+
+               if (config_rom) {
+                       dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+                                         ohci->next_config_rom,
+                                         ohci->next_config_rom_bus);
+                       ohci->next_config_rom = NULL;
+               }
                return -EIO;
        }
 
index 41841a3..17cef86 100644 (file)
@@ -1198,6 +1198,10 @@ static int sbp2_remove(struct device *dev)
 {
        struct fw_unit *unit = fw_unit(dev);
        struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
+       struct sbp2_logical_unit *lu;
+
+       list_for_each_entry(lu, &tgt->lu_list, link)
+               cancel_delayed_work_sync(&lu->work);
 
        sbp2_target_put(tgt);
        return 0;
index 68810fd..aa83de9 100644 (file)
@@ -420,7 +420,7 @@ static efi_status_t gsmi_get_next_variable(unsigned long *name_size,
 
 static efi_status_t gsmi_set_variable(efi_char16_t *name,
                                      efi_guid_t *vendor,
-                                     unsigned long attr,
+                                     u32 attr,
                                      unsigned long data_size,
                                      void *data)
 {
index 82db185..fe738f0 100644 (file)
@@ -499,6 +499,7 @@ void drm_connector_cleanup(struct drm_connector *connector)
        mutex_lock(&dev->mode_config.mutex);
        drm_mode_object_put(dev, &connector->base);
        list_del(&connector->head);
+       dev->mode_config.num_connector--;
        mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_connector_cleanup);
@@ -529,6 +530,7 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
        mutex_lock(&dev->mode_config.mutex);
        drm_mode_object_put(dev, &encoder->base);
        list_del(&encoder->head);
+       dev->mode_config.num_encoder--;
        mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
index 802b61a..f7c6854 100644 (file)
@@ -256,7 +256,6 @@ int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
 {
        printk(KERN_ERR "panic occurred, switching back to text console\n");
        return drm_fb_helper_force_kernel_mode();
-       return 0;
 }
 EXPORT_SYMBOL(drm_fb_helper_panic);
 
index a8ab626..3c395a5 100644 (file)
@@ -499,7 +499,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
        seq_printf(m, "Interrupts received: %d\n",
                   atomic_read(&dev_priv->irq_received));
        for (i = 0; i < I915_NUM_RINGS; i++) {
-               if (IS_GEN6(dev)) {
+               if (IS_GEN6(dev) || IS_GEN7(dev)) {
                        seq_printf(m, "Graphics Interrupt mask (%s):    %08x\n",
                                   dev_priv->ring[i].name,
                                   I915_READ_IMR(&dev_priv->ring[i]));
index feb4f16..7916bd9 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/io-mapping.h>
 #include <linux/i2c.h>
 #include <drm/intel-gtt.h>
+#include <linux/backlight.h>
 
 /* General customization:
  */
@@ -690,6 +691,7 @@ typedef struct drm_i915_private {
        int child_dev_num;
        struct child_device_config *child_dev;
        struct drm_connector *int_lvds_connector;
+       struct drm_connector *int_edp_connector;
 
        bool mchbar_need_disable;
 
@@ -723,6 +725,8 @@ typedef struct drm_i915_private {
        /* list of fbdev register on this device */
        struct intel_fbdev *fbdev;
 
+       struct backlight_device *backlight;
+
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
 
index 02f96fd..9cbb0cd 100644 (file)
@@ -2058,8 +2058,10 @@ void intel_irq_init(struct drm_device *dev)
                dev->driver->get_vblank_counter = gm45_get_vblank_counter;
        }
 
-
-       dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
+       else
+               dev->driver->get_vblank_timestamp = NULL;
        dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
 
        if (IS_IVYBRIDGE(dev)) {
index d1331f7..542453f 100644 (file)
 # define MI_FLUSH_ENABLE                               (1 << 11)
 
 #define GFX_MODE       0x02520
+#define GFX_MODE_GEN7  0x0229c
 #define   GFX_RUN_LIST_ENABLE          (1<<15)
 #define   GFX_TLB_INVALIDATE_ALWAYS    (1<<13)
 #define   GFX_SURFACE_FAULT_ENABLE     (1<<12)
 #define   GFX_PSMI_GRANULARITY         (1<<10)
 #define   GFX_PPGTT_ENABLE             (1<<9)
 
+#define GFX_MODE_ENABLE(bit) (((bit) << 16) | (bit))
+#define GFX_MODE_DISABLE(bit) (((bit) << 16) | (0))
+
 #define SCPD0          0x0209c /* 915+ only */
 #define IER            0x020a0
 #define IIR            0x020a4
 #define   ADPA_PIPE_SELECT_MASK        (1<<30)
 #define   ADPA_PIPE_A_SELECT   0
 #define   ADPA_PIPE_B_SELECT   (1<<30)
+#define   ADPA_PIPE_SELECT(pipe) ((pipe) << 30)
 #define   ADPA_USE_VGA_HVPOLARITY (1<<15)
 #define   ADPA_SETS_HVPOLARITY 0
 #define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
 /* Selects pipe B for LVDS data.  Must be set on pre-965. */
 #define   LVDS_PIPEB_SELECT            (1 << 30)
 #define   LVDS_PIPE_MASK               (1 << 30)
+#define   LVDS_PIPE(pipe)              ((pipe) << 30)
 /* LVDS dithering flag on 965/g4x platform */
 #define   LVDS_ENABLE_DITHER           (1 << 25)
 /* LVDS sync polarity flags. Set to invert (i.e. negative) */
 #define   LVDS_B0B3_POWER_DOWN         (0 << 2)
 #define   LVDS_B0B3_POWER_UP           (3 << 2)
 
-#define LVDS_PIPE_ENABLED(V, P) \
-       (((V) & (LVDS_PIPE_MASK | LVDS_PORT_EN)) == ((P) << 30 | LVDS_PORT_EN))
-
 /* Video Data Island Packet control */
 #define VIDEO_DIP_DATA         0x61178
 #define VIDEO_DIP_CTL          0x61170
 #define  ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
 #define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 
-#define ADPA_PIPE_ENABLED(V, P) \
-       (((V) & (ADPA_TRANS_SELECT_MASK | ADPA_DAC_ENABLE)) == ((P) << 30 | ADPA_DAC_ENABLE))
-
 /* or SDVOB */
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
 #define  TRANSCODER_A   (0)
 #define  TRANSCODER_B   (1 << 30)
+#define  TRANSCODER(pipe)      ((pipe) << 30)
 #define  TRANSCODER_MASK   (1 << 30)
 #define  COLOR_FORMAT_8bpc      (0)
 #define  COLOR_FORMAT_12bpc     (3 << 26)
 #define  HSYNC_ACTIVE_HIGH      (1 << 3)
 #define  PORT_DETECTED          (1 << 2)
 
-#define HDMI_PIPE_ENABLED(V, P) \
-       (((V) & (TRANSCODER_MASK | PORT_ENABLE)) == ((P) << 30 | PORT_ENABLE))
-
 /* PCH SDVOB multiplex with HDMIB */
 #define PCH_SDVOB      HDMIB
 
 #define  PORT_TRANS_B_SEL_CPT  (1<<29)
 #define  PORT_TRANS_C_SEL_CPT  (2<<29)
 #define  PORT_TRANS_SEL_MASK   (3<<29)
+#define  PORT_TRANS_SEL_CPT(pipe)      ((pipe) << 29)
 
 #define TRANS_DP_CTL_A         0xe0300
 #define TRANS_DP_CTL_B         0xe1300
index 87677d6..f107423 100644 (file)
@@ -871,7 +871,8 @@ int i915_restore_state(struct drm_device *dev)
        }
        mutex_unlock(&dev->struct_mutex);
 
-       intel_init_clock_gating(dev);
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               intel_init_clock_gating(dev);
 
        if (IS_IRONLAKE_M(dev)) {
                ironlake_enable_drps(dev);
index 35364e6..56a8554 100644 (file)
@@ -878,7 +878,7 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
        int pp_reg, lvds_reg;
        u32 val;
        enum pipe panel_pipe = PIPE_A;
-       bool locked = locked;
+       bool locked = true;
 
        if (HAS_PCH_SPLIT(dev_priv->dev)) {
                pp_reg = PCH_PP_CONTROL;
@@ -980,8 +980,8 @@ static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
             pipe_name(pipe));
 }
 
-static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe,
-                           int reg, u32 port_sel, u32 val)
+static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
+                           enum pipe pipe, u32 port_sel, u32 val)
 {
        if ((val & DP_PORT_EN) == 0)
                return false;
@@ -998,11 +998,58 @@ static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe,
        return true;
 }
 
+static bool hdmi_pipe_enabled(struct drm_i915_private *dev_priv,
+                             enum pipe pipe, u32 val)
+{
+       if ((val & PORT_ENABLE) == 0)
+               return false;
+
+       if (HAS_PCH_CPT(dev_priv->dev)) {
+               if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe))
+                       return false;
+       } else {
+               if ((val & TRANSCODER_MASK) != TRANSCODER(pipe))
+                       return false;
+       }
+       return true;
+}
+
+static bool lvds_pipe_enabled(struct drm_i915_private *dev_priv,
+                             enum pipe pipe, u32 val)
+{
+       if ((val & LVDS_PORT_EN) == 0)
+               return false;
+
+       if (HAS_PCH_CPT(dev_priv->dev)) {
+               if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe))
+                       return false;
+       } else {
+               if ((val & LVDS_PIPE_MASK) != LVDS_PIPE(pipe))
+                       return false;
+       }
+       return true;
+}
+
+static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv,
+                             enum pipe pipe, u32 val)
+{
+       if ((val & ADPA_DAC_ENABLE) == 0)
+               return false;
+       if (HAS_PCH_CPT(dev_priv->dev)) {
+               if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe))
+                       return false;
+       } else {
+               if ((val & ADPA_PIPE_SELECT_MASK) != ADPA_PIPE_SELECT(pipe))
+                       return false;
+       }
+       return true;
+}
+
 static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
                                   enum pipe pipe, int reg, u32 port_sel)
 {
        u32 val = I915_READ(reg);
-       WARN(dp_pipe_enabled(dev_priv, pipe, reg, port_sel, val),
+       WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val),
             "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
 }
@@ -1011,7 +1058,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
                                     enum pipe pipe, int reg)
 {
        u32 val = I915_READ(reg);
-       WARN(HDMI_PIPE_ENABLED(val, pipe),
+       WARN(hdmi_pipe_enabled(dev_priv, val, pipe),
             "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
 }
@@ -1028,13 +1075,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
 
        reg = PCH_ADPA;
        val = I915_READ(reg);
-       WARN(ADPA_PIPE_ENABLED(val, pipe),
+       WARN(adpa_pipe_enabled(dev_priv, val, pipe),
             "PCH VGA enabled on transcoder %c, should be disabled\n",
             pipe_name(pipe));
 
        reg = PCH_LVDS;
        val = I915_READ(reg);
-       WARN(LVDS_PIPE_ENABLED(val, pipe),
+       WARN(lvds_pipe_enabled(dev_priv, val, pipe),
             "PCH LVDS enabled on transcoder %c, should be disabled\n",
             pipe_name(pipe));
 
@@ -1360,7 +1407,7 @@ static void disable_pch_dp(struct drm_i915_private *dev_priv,
                           enum pipe pipe, int reg, u32 port_sel)
 {
        u32 val = I915_READ(reg);
-       if (dp_pipe_enabled(dev_priv, pipe, reg, port_sel, val)) {
+       if (dp_pipe_enabled(dev_priv, pipe, port_sel, val)) {
                DRM_DEBUG_KMS("Disabling pch dp %x on pipe %d\n", reg, pipe);
                I915_WRITE(reg, val & ~DP_PORT_EN);
        }
@@ -1370,7 +1417,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
                             enum pipe pipe, int reg)
 {
        u32 val = I915_READ(reg);
-       if (HDMI_PIPE_ENABLED(val, pipe)) {
+       if (hdmi_pipe_enabled(dev_priv, val, pipe)) {
                DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n",
                              reg, pipe);
                I915_WRITE(reg, val & ~PORT_ENABLE);
@@ -1392,12 +1439,13 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
 
        reg = PCH_ADPA;
        val = I915_READ(reg);
-       if (ADPA_PIPE_ENABLED(val, pipe))
+       if (adpa_pipe_enabled(dev_priv, val, pipe))
                I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
 
        reg = PCH_LVDS;
        val = I915_READ(reg);
-       if (LVDS_PIPE_ENABLED(val, pipe)) {
+       if (lvds_pipe_enabled(dev_priv, val, pipe)) {
+               DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val);
                I915_WRITE(reg, val & ~LVDS_PORT_EN);
                POSTING_READ(reg);
                udelay(100);
@@ -5049,6 +5097,81 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        return ret;
 }
 
+static void ironlake_update_pch_refclk(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_crtc *crtc;
+       struct intel_encoder *encoder;
+       struct intel_encoder *has_edp_encoder = NULL;
+       u32 temp;
+       bool has_lvds = false;
+
+       /* We need to take the global config into account */
+       list_for_each_entry(crtc, &mode_config->crtc_list, head) {
+               if (!crtc->enabled)
+                       continue;
+
+               list_for_each_entry(encoder, &mode_config->encoder_list,
+                                   base.head) {
+                       if (encoder->base.crtc != crtc)
+                               continue;
+
+                       switch (encoder->type) {
+                       case INTEL_OUTPUT_LVDS:
+                               has_lvds = true;
+                       case INTEL_OUTPUT_EDP:
+                               has_edp_encoder = encoder;
+                               break;
+                       }
+               }
+       }
+
+       /* Ironlake: try to setup display ref clock before DPLL
+        * enabling. This is only under driver's control after
+        * PCH B stepping, previous chipset stepping should be
+        * ignoring this setting.
+        */
+       temp = I915_READ(PCH_DREF_CONTROL);
+       /* Always enable nonspread source */
+       temp &= ~DREF_NONSPREAD_SOURCE_MASK;
+       temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+       temp &= ~DREF_SSC_SOURCE_MASK;
+       temp |= DREF_SSC_SOURCE_ENABLE;
+       I915_WRITE(PCH_DREF_CONTROL, temp);
+
+       POSTING_READ(PCH_DREF_CONTROL);
+       udelay(200);
+
+       if (has_edp_encoder) {
+               if (intel_panel_use_ssc(dev_priv)) {
+                       temp |= DREF_SSC1_ENABLE;
+                       I915_WRITE(PCH_DREF_CONTROL, temp);
+
+                       POSTING_READ(PCH_DREF_CONTROL);
+                       udelay(200);
+               }
+               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+
+               /* Enable CPU source on CPU attached eDP */
+               if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+                       if (intel_panel_use_ssc(dev_priv))
+                               temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+                       else
+                               temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+               } else {
+                       /* Enable SSC on PCH eDP if needed */
+                       if (intel_panel_use_ssc(dev_priv)) {
+                               DRM_ERROR("enabling SSC on PCH\n");
+                               temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
+                       }
+               }
+               I915_WRITE(PCH_DREF_CONTROL, temp);
+               POSTING_READ(PCH_DREF_CONTROL);
+               udelay(200);
+       }
+}
+
 static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                                  struct drm_display_mode *mode,
                                  struct drm_display_mode *adjusted_mode,
@@ -5244,49 +5367,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
                             &m_n);
 
-       /* Ironlake: try to setup display ref clock before DPLL
-        * enabling. This is only under driver's control after
-        * PCH B stepping, previous chipset stepping should be
-        * ignoring this setting.
-        */
-       temp = I915_READ(PCH_DREF_CONTROL);
-       /* Always enable nonspread source */
-       temp &= ~DREF_NONSPREAD_SOURCE_MASK;
-       temp |= DREF_NONSPREAD_SOURCE_ENABLE;
-       temp &= ~DREF_SSC_SOURCE_MASK;
-       temp |= DREF_SSC_SOURCE_ENABLE;
-       I915_WRITE(PCH_DREF_CONTROL, temp);
-
-       POSTING_READ(PCH_DREF_CONTROL);
-       udelay(200);
-
-       if (has_edp_encoder) {
-               if (intel_panel_use_ssc(dev_priv)) {
-                       temp |= DREF_SSC1_ENABLE;
-                       I915_WRITE(PCH_DREF_CONTROL, temp);
-
-                       POSTING_READ(PCH_DREF_CONTROL);
-                       udelay(200);
-               }
-               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-
-               /* Enable CPU source on CPU attached eDP */
-               if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-                       if (intel_panel_use_ssc(dev_priv))
-                               temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
-                       else
-                               temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
-               } else {
-                       /* Enable SSC on PCH eDP if needed */
-                       if (intel_panel_use_ssc(dev_priv)) {
-                               DRM_ERROR("enabling SSC on PCH\n");
-                               temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
-                       }
-               }
-               I915_WRITE(PCH_DREF_CONTROL, temp);
-               POSTING_READ(PCH_DREF_CONTROL);
-               udelay(200);
-       }
+       ironlake_update_pch_refclk(dev);
 
        fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
        if (has_reduced_clock)
@@ -7157,8 +7238,6 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_encoder_clones(dev, encoder->clone_mask);
        }
 
-       intel_panel_setup_backlight(dev);
-
        /* disable all the possible outputs/crtcs before entering KMS mode */
        drm_helper_disable_unused_functions(dev);
 }
index 0feae90..44fef5e 100644 (file)
@@ -1841,6 +1841,11 @@ done:
 static void
 intel_dp_destroy (struct drm_connector *connector)
 {
+       struct drm_device *dev = connector->dev;
+
+       if (intel_dpd_is_edp(dev))
+               intel_panel_destroy_backlight(dev);
+
        drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
        kfree(connector);
@@ -2072,6 +2077,8 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                                        DRM_MODE_TYPE_PREFERRED;
                        }
                }
+               dev_priv->int_edp_connector = connector;
+               intel_panel_setup_backlight(dev);
        }
 
        intel_dp_add_properties(intel_dp, connector);
index 7b330e7..0b2ee9d 100644 (file)
@@ -297,9 +297,10 @@ extern void intel_pch_panel_fitting(struct drm_device *dev,
 extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
 extern u32 intel_panel_get_backlight(struct drm_device *dev);
 extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
-extern void intel_panel_setup_backlight(struct drm_device *dev);
+extern int intel_panel_setup_backlight(struct drm_device *dev);
 extern void intel_panel_enable_backlight(struct drm_device *dev);
 extern void intel_panel_disable_backlight(struct drm_device *dev);
+extern void intel_panel_destroy_backlight(struct drm_device *dev);
 extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
index 2e8ddfc..31da77f 100644 (file)
@@ -72,14 +72,16 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds)
 {
        struct drm_device *dev = intel_lvds->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 ctl_reg, lvds_reg;
+       u32 ctl_reg, lvds_reg, stat_reg;
 
        if (HAS_PCH_SPLIT(dev)) {
                ctl_reg = PCH_PP_CONTROL;
                lvds_reg = PCH_LVDS;
+               stat_reg = PCH_PP_STATUS;
        } else {
                ctl_reg = PP_CONTROL;
                lvds_reg = LVDS;
+               stat_reg = PP_STATUS;
        }
 
        I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
@@ -94,17 +96,16 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds)
                DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
                              intel_lvds->pfit_control,
                              intel_lvds->pfit_pgm_ratios);
-               if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) {
-                       DRM_ERROR("timed out waiting for panel to power off\n");
-               } else {
-                       I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
-                       I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
-                       intel_lvds->pfit_dirty = false;
-               }
+
+               I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
+               I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
+               intel_lvds->pfit_dirty = false;
        }
 
        I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
        POSTING_READ(lvds_reg);
+       if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000))
+               DRM_ERROR("timed out waiting for panel to power on\n");
 
        intel_panel_enable_backlight(dev);
 }
@@ -113,24 +114,25 @@ static void intel_lvds_disable(struct intel_lvds *intel_lvds)
 {
        struct drm_device *dev = intel_lvds->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 ctl_reg, lvds_reg;
+       u32 ctl_reg, lvds_reg, stat_reg;
 
        if (HAS_PCH_SPLIT(dev)) {
                ctl_reg = PCH_PP_CONTROL;
                lvds_reg = PCH_LVDS;
+               stat_reg = PCH_PP_STATUS;
        } else {
                ctl_reg = PP_CONTROL;
                lvds_reg = LVDS;
+               stat_reg = PP_STATUS;
        }
 
        intel_panel_disable_backlight(dev);
 
        I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
+       if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000))
+               DRM_ERROR("timed out waiting for panel to power off\n");
 
        if (intel_lvds->pfit_control) {
-               if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
-                       DRM_ERROR("timed out waiting for panel to power off\n");
-
                I915_WRITE(PFIT_CONTROL, 0);
                intel_lvds->pfit_dirty = true;
        }
@@ -398,53 +400,21 @@ out:
 
 static void intel_lvds_prepare(struct drm_encoder *encoder)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
-       /* We try to do the minimum that is necessary in order to unlock
-        * the registers for mode setting.
-        *
-        * On Ironlake, this is quite simple as we just set the unlock key
-        * and ignore all subtleties. (This may cause some issues...)
-        *
+       /*
         * Prior to Ironlake, we must disable the pipe if we want to adjust
         * the panel fitter. However at all other times we can just reset
         * the registers regardless.
         */
-
-       if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(PCH_PP_CONTROL,
-                          I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
-       } else if (intel_lvds->pfit_dirty) {
-               I915_WRITE(PP_CONTROL,
-                          (I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS)
-                          & ~POWER_TARGET_ON);
-       } else {
-               I915_WRITE(PP_CONTROL,
-                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
-       }
+       if (!HAS_PCH_SPLIT(encoder->dev) && intel_lvds->pfit_dirty)
+               intel_lvds_disable(intel_lvds);
 }
 
 static void intel_lvds_commit(struct drm_encoder *encoder)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
-       /* Undo any unlocking done in prepare to prevent accidental
-        * adjustment of the registers.
-        */
-       if (HAS_PCH_SPLIT(dev)) {
-               u32 val = I915_READ(PCH_PP_CONTROL);
-               if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
-                       I915_WRITE(PCH_PP_CONTROL, val & 0x3);
-       } else {
-               u32 val = I915_READ(PP_CONTROL);
-               if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
-                       I915_WRITE(PP_CONTROL, val & 0x3);
-       }
-
        /* Always do a full power on as we do not know what state
         * we were left in.
         */
@@ -582,6 +552,8 @@ static void intel_lvds_destroy(struct drm_connector *connector)
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       intel_panel_destroy_backlight(dev);
+
        if (dev_priv->lid_notifier.notifier_call)
                acpi_lid_notifier_unregister(&dev_priv->lid_notifier);
        drm_sysfs_connector_remove(connector);
@@ -1040,6 +1012,19 @@ out:
                pwm = I915_READ(BLC_PWM_PCH_CTL1);
                pwm |= PWM_PCH_ENABLE;
                I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
+               /*
+                * Unlock registers and just
+                * leave them unlocked
+                */
+               I915_WRITE(PCH_PP_CONTROL,
+                          I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
+       } else {
+               /*
+                * Unlock registers and just
+                * leave them unlocked
+                */
+               I915_WRITE(PP_CONTROL,
+                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
        }
        dev_priv->lid_notifier.notifier_call = intel_lid_notify;
        if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) {
@@ -1049,6 +1034,9 @@ out:
        /* keep the LVDS connector */
        dev_priv->int_lvds_connector = connector;
        drm_sysfs_connector_add(connector);
+
+       intel_panel_setup_backlight(dev);
+
        return true;
 
 failed:
index b7c5ddb..b8e8158 100644 (file)
@@ -227,7 +227,6 @@ void intel_opregion_asle_intr(struct drm_device *dev)
        asle->aslc = asle_stat;
 }
 
-/* Only present on Ironlake+ */
 void intel_opregion_gse_intr(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
index 05f500c..a9e0c7b 100644 (file)
@@ -277,7 +277,7 @@ void intel_panel_enable_backlight(struct drm_device *dev)
        dev_priv->backlight_enabled = true;
 }
 
-void intel_panel_setup_backlight(struct drm_device *dev)
+static void intel_panel_init_backlight(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -309,3 +309,73 @@ intel_panel_detect(struct drm_device *dev)
 
        return connector_status_unknown;
 }
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+static int intel_panel_update_status(struct backlight_device *bd)
+{
+       struct drm_device *dev = bl_get_data(bd);
+       intel_panel_set_backlight(dev, bd->props.brightness);
+       return 0;
+}
+
+static int intel_panel_get_brightness(struct backlight_device *bd)
+{
+       struct drm_device *dev = bl_get_data(bd);
+       return intel_panel_get_backlight(dev);
+}
+
+static const struct backlight_ops intel_panel_bl_ops = {
+       .update_status = intel_panel_update_status,
+       .get_brightness = intel_panel_get_brightness,
+};
+
+int intel_panel_setup_backlight(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct backlight_properties props;
+       struct drm_connector *connector;
+
+       intel_panel_init_backlight(dev);
+
+       if (dev_priv->int_lvds_connector)
+               connector = dev_priv->int_lvds_connector;
+       else if (dev_priv->int_edp_connector)
+               connector = dev_priv->int_edp_connector;
+       else
+               return -ENODEV;
+
+       props.type = BACKLIGHT_RAW;
+       props.max_brightness = intel_panel_get_max_backlight(dev);
+       dev_priv->backlight =
+               backlight_device_register("intel_backlight",
+                                         &connector->kdev, dev,
+                                         &intel_panel_bl_ops, &props);
+
+       if (IS_ERR(dev_priv->backlight)) {
+               DRM_ERROR("Failed to register backlight: %ld\n",
+                         PTR_ERR(dev_priv->backlight));
+               dev_priv->backlight = NULL;
+               return -ENODEV;
+       }
+       dev_priv->backlight->props.brightness = intel_panel_get_backlight(dev);
+       return 0;
+}
+
+void intel_panel_destroy_backlight(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (dev_priv->backlight)
+               backlight_device_unregister(dev_priv->backlight);
+}
+#else
+int intel_panel_setup_backlight(struct drm_device *dev)
+{
+       intel_panel_init_backlight(dev);
+       return 0;
+}
+
+void intel_panel_destroy_backlight(struct drm_device *dev)
+{
+       return;
+}
+#endif
index 47b9b27..c30626e 100644 (file)
@@ -290,6 +290,10 @@ static int init_render_ring(struct intel_ring_buffer *ring)
                if (IS_GEN6(dev) || IS_GEN7(dev))
                        mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
                I915_WRITE(MI_MODE, mode);
+               if (IS_GEN7(dev))
+                       I915_WRITE(GFX_MODE_GEN7,
+                                  GFX_MODE_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
+                                  GFX_MODE_ENABLE(GFX_REPLAY_MODE));
        }
 
        if (INTEL_INFO(dev)->gen >= 6) {
index 8d02d87..c919cfc 100644 (file)
@@ -530,7 +530,8 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
                nouveau_gpuobj_ref(NULL, &obj);
                if (ret)
                        return ret;
-       } else {
+       } else
+       if (USE_SEMA(dev)) {
                /* map fence bo into channel's vm */
                ret = nouveau_bo_vma_add(dev_priv->fence.bo, chan->vm,
                                         &chan->fence.vma);
index c444cad..2706cb3 100644 (file)
@@ -37,8 +37,11 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
                return -ENOMEM;
 
        nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL);
-       if (!nvbe->ttm_alloced)
+       if (!nvbe->ttm_alloced) {
+               kfree(nvbe->pages);
+               nvbe->pages = NULL;
                return -ENOMEM;
+       }
 
        nvbe->nr_pages = 0;
        while (num_pages--) {
@@ -126,7 +129,7 @@ nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 
                for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) {
                        nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3);
-                       dma_offset += NV_CTXDMA_PAGE_SIZE;
+                       offset_l += NV_CTXDMA_PAGE_SIZE;
                }
        }
 
index 118261d..5e45398 100644 (file)
@@ -781,11 +781,20 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        struct drm_device *dev = crtc->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
-       struct drm_framebuffer *drm_fb = nv_crtc->base.fb;
-       struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
+       struct drm_framebuffer *drm_fb;
+       struct nouveau_framebuffer *fb;
        int arb_burst, arb_lwm;
        int ret;
 
+       NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
+
+       /* no fb bound */
+       if (!atomic && !crtc->fb) {
+               NV_DEBUG_KMS(dev, "No FB bound\n");
+               return 0;
+       }
+
+
        /* If atomic, we want to switch to the fb we were passed, so
         * now we update pointers to do that.  (We don't pin; just
         * assume we're already pinned and update the base address.)
@@ -794,6 +803,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
                drm_fb = passed_fb;
                fb = nouveau_framebuffer(passed_fb);
        } else {
+               drm_fb = crtc->fb;
+               fb = nouveau_framebuffer(crtc->fb);
                /* If not atomic, we can go ahead and pin, and unpin the
                 * old fb we were passed.
                 */
index 46ad59e..5d98907 100644 (file)
@@ -519,12 +519,18 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
        struct drm_device *dev = nv_crtc->base.dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_channel *evo = nv50_display(dev)->master;
-       struct drm_framebuffer *drm_fb = nv_crtc->base.fb;
-       struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
+       struct drm_framebuffer *drm_fb;
+       struct nouveau_framebuffer *fb;
        int ret;
 
        NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
+       /* no fb bound */
+       if (!atomic && !crtc->fb) {
+               NV_DEBUG_KMS(dev, "No FB bound\n");
+               return 0;
+       }
+
        /* If atomic, we want to switch to the fb we were passed, so
         * now we update pointers to do that.  (We don't pin; just
         * assume we're already pinned and update the base address.)
@@ -533,6 +539,8 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
                drm_fb = passed_fb;
                fb = nouveau_framebuffer(passed_fb);
        } else {
+               drm_fb = crtc->fb;
+               fb = nouveau_framebuffer(crtc->fb);
                /* If not atomic, we can go ahead and pin, and unpin the
                 * old fb we were passed.
                 */
index 645b84b..7ad43c6 100644 (file)
@@ -613,6 +613,18 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector,
        return true;
 }
 
+bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
+{
+       u8 link_status[DP_LINK_STATUS_SIZE];
+       struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
+
+       if (!radeon_dp_get_link_status(radeon_connector, link_status))
+               return false;
+       if (dp_channel_eq_ok(link_status, dig->dp_lane_count))
+               return false;
+       return true;
+}
+
 struct radeon_dp_link_train_info {
        struct radeon_device *rdev;
        struct drm_encoder *encoder;
index 14dce9f..dc0a5b5 100644 (file)
@@ -41,6 +41,31 @@ static void evergreen_gpu_init(struct radeon_device *rdev);
 void evergreen_fini(struct radeon_device *rdev);
 static void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 
+void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
+{
+       u16 ctl, v;
+       int cap, err;
+
+       cap = pci_pcie_cap(rdev->pdev);
+       if (!cap)
+               return;
+
+       err = pci_read_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, &ctl);
+       if (err)
+               return;
+
+       v = (ctl & PCI_EXP_DEVCTL_READRQ) >> 12;
+
+       /* if bios or OS sets MAX_READ_REQUEST_SIZE to an invalid value, fix it
+        * to avoid hangs or perfomance issues
+        */
+       if ((v == 0) || (v == 6) || (v == 7)) {
+               ctl &= ~PCI_EXP_DEVCTL_READRQ;
+               ctl |= (2 << 12);
+               pci_write_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, ctl);
+       }
+}
+
 void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc)
 {
        /* enable the pflip int */
@@ -743,7 +768,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
                    !evergreen_average_bandwidth_vs_available_bandwidth(&wm) ||
                    !evergreen_check_latency_hiding(&wm) ||
                    (rdev->disp_priority == 2)) {
-                       DRM_INFO("force priority to high\n");
+                       DRM_DEBUG_KMS("force priority to high\n");
                        priority_a_cnt |= PRIORITY_ALWAYS_ON;
                        priority_b_cnt |= PRIORITY_ALWAYS_ON;
                }
@@ -1357,6 +1382,7 @@ int evergreen_cp_resume(struct radeon_device *rdev)
                                 SOFT_RESET_PA |
                                 SOFT_RESET_SH |
                                 SOFT_RESET_VGT |
+                                SOFT_RESET_SPI |
                                 SOFT_RESET_SX));
        RREG32(GRBM_SOFT_RESET);
        mdelay(15);
@@ -1862,6 +1888,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
 
        WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
 
+       evergreen_fix_pci_max_read_req_size(rdev);
+
        cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & ~2;
 
        cc_gc_shader_pipe_config |=
index 44c4750..cbf57d7 100644 (file)
@@ -39,6 +39,7 @@ extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
 extern void evergreen_mc_program(struct radeon_device *rdev);
 extern void evergreen_irq_suspend(struct radeon_device *rdev);
 extern int evergreen_mc_init(struct radeon_device *rdev);
+extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
 
 #define EVERGREEN_PFP_UCODE_SIZE 1120
 #define EVERGREEN_PM4_UCODE_SIZE 1376
@@ -669,6 +670,8 @@ static void cayman_gpu_init(struct radeon_device *rdev)
 
        WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
 
+       evergreen_fix_pci_max_read_req_size(rdev);
+
        mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
        mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
 
@@ -1159,6 +1162,7 @@ int cayman_cp_resume(struct radeon_device *rdev)
                                 SOFT_RESET_PA |
                                 SOFT_RESET_SH |
                                 SOFT_RESET_VGT |
+                                SOFT_RESET_SPI |
                                 SOFT_RESET_SX));
        RREG32(GRBM_SOFT_RESET);
        mdelay(15);
index dcd0863..b6e18c8 100644 (file)
@@ -219,6 +219,9 @@ void radeon_get_clock_info(struct drm_device *dev)
                } else {
                        DRM_INFO("Using generic clock info\n");
 
+                       /* may need to be per card */
+                       rdev->clock.max_pixel_clock = 35000;
+
                        if (rdev->flags & RADEON_IS_IGP) {
                                p1pll->reference_freq = 1432;
                                p2pll->reference_freq = 1432;
index e0138b6..6367524 100644 (file)
@@ -3298,6 +3298,14 @@ void radeon_combios_asic_init(struct drm_device *dev)
            rdev->pdev->subsystem_device == 0x30a4)
                return;
 
+       /* quirk for rs4xx Compaq Presario V5245EU laptop to make it resume
+        * - it hangs on resume inside the dynclk 1 table.
+        */
+       if (rdev->family == CHIP_RS480 &&
+           rdev->pdev->subsystem_vendor == 0x103c &&
+           rdev->pdev->subsystem_device == 0x30ae)
+               return;
+
        /* DYN CLK 1 */
        table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
        if (table)
index 6d6b5f1..c4b8741 100644 (file)
@@ -60,18 +60,20 @@ void radeon_connector_hotplug(struct drm_connector *connector)
 
        radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 
-       /* powering up/down the eDP panel generates hpd events which
-        * can interfere with modesetting.
-        */
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+       /* if the connector is already off, don't turn it back on */
+       if (connector->dpms != DRM_MODE_DPMS_ON)
                return;
 
-       /* pre-r600 did not always have the hpd pins mapped accurately to connectors */
-       if (rdev->family >= CHIP_R600) {
-               if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
+       /* just deal with DP (not eDP) here. */
+       if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+               int saved_dpms = connector->dpms;
+
+               if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) &&
+                   radeon_dp_needs_link_train(radeon_connector))
                        drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
                else
                        drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+               connector->dpms = saved_dpms;
        }
 }
 
@@ -464,6 +466,16 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
                    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
                        return true;
        }
+       /* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100
+        * (RS690M) sends data to i2c bus for a HDMI connector that
+        * is not implemented */
+       if ((dev->pdev->device == 0x791f) &&
+           (dev->pdev->subsystem_vendor == 0x1179) &&
+           (dev->pdev->subsystem_device == 0xff68)) {
+               if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+                       return true;
+       }
 
        /* Default: no EDID header probe required for DDC probing */
        return false;
@@ -474,11 +486,19 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+       struct drm_display_mode *t, *mode;
+
+       /* If the EDID preferred mode doesn't match the native mode, use it */
+       list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
+               if (mode->type & DRM_MODE_TYPE_PREFERRED) {
+                       if (mode->hdisplay != native_mode->hdisplay ||
+                           mode->vdisplay != native_mode->vdisplay)
+                               memcpy(native_mode, mode, sizeof(*mode));
+               }
+       }
 
        /* Try to get native mode details from EDID if necessary */
        if (!native_mode->clock) {
-               struct drm_display_mode *t, *mode;
-
                list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
                        if (mode->hdisplay == native_mode->hdisplay &&
                            mode->vdisplay == native_mode->vdisplay) {
@@ -489,6 +509,7 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
                        }
                }
        }
+
        if (!native_mode->clock) {
                DRM_DEBUG_KMS("No LVDS native mode details, disabling RMX\n");
                radeon_encoder->rmx_type = RMX_OFF;
@@ -1276,12 +1297,33 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                if (!radeon_dig_connector->edp_on)
                        atombios_set_edp_panel_power(connector,
                                                     ATOM_TRANSMITTER_ACTION_POWER_OFF);
-       } else {
-               /* need to setup ddc on the bridge */
-               if (radeon_connector_encoder_is_dp_bridge(connector)) {
+       } else if (radeon_connector_encoder_is_dp_bridge(connector)) {
+               /* DP bridges are always DP */
+               radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
+               /* get the DPCD from the bridge */
+               radeon_dp_getdpcd(radeon_connector);
+
+               if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
+                       ret = connector_status_connected;
+               else {
+                       /* need to setup ddc on the bridge */
                        if (encoder)
                                radeon_atom_ext_encoder_setup_ddc(encoder);
+                       if (radeon_ddc_probe(radeon_connector,
+                                            radeon_connector->requires_extended_probe))
+                               ret = connector_status_connected;
+               }
+
+               if ((ret == connector_status_disconnected) &&
+                   radeon_connector->dac_load_detect) {
+                       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+                       struct drm_encoder_helper_funcs *encoder_funcs;
+                       if (encoder) {
+                               encoder_funcs = encoder->helper_private;
+                               ret = encoder_funcs->detect(encoder, connector);
+                       }
                }
+       } else {
                radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
                if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
                        ret = connector_status_connected;
@@ -1297,16 +1339,6 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                                        ret = connector_status_connected;
                        }
                }
-
-               if ((ret == connector_status_disconnected) &&
-                   radeon_connector->dac_load_detect) {
-                       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
-                       struct drm_encoder_helper_funcs *encoder_funcs;
-                       if (encoder) {
-                               encoder_funcs = encoder->helper_private;
-                               ret = encoder_funcs->detect(encoder, connector);
-                       }
-               }
        }
 
        radeon_connector_update_scratch_regs(connector, ret);
index 440e6ec..b51e157 100644 (file)
@@ -32,6 +32,7 @@
 #include <drm/radeon_drm.h>
 #include <linux/vgaarb.h>
 #include <linux/vga_switcheroo.h>
+#include <linux/efi.h>
 #include "radeon_reg.h"
 #include "radeon.h"
 #include "atom.h"
@@ -300,6 +301,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64
                mc->mc_vram_size = mc->aper_size;
        }
        mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
+       if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size)
+               mc->real_vram_size = radeon_vram_limit;
        dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
                        mc->mc_vram_size >> 20, mc->vram_start,
                        mc->vram_end, mc->real_vram_size >> 20);
@@ -348,6 +351,9 @@ bool radeon_card_posted(struct radeon_device *rdev)
 {
        uint32_t reg;
 
+       if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
+               return false;
+
        /* first check CRTCs */
        if (ASIC_IS_DCE41(rdev)) {
                reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
index 1a85894..6cc17fb 100644 (file)
@@ -707,16 +707,21 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
                radeon_router_select_ddc_port(radeon_connector);
 
        if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
-           (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
+           (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) ||
+           radeon_connector_encoder_is_dp_bridge(&radeon_connector->base)) {
                struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
+
                if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
                     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus)
-                       radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter);
-       }
-       if (!radeon_connector->ddc_bus)
-               return -1;
-       if (!radeon_connector->edid) {
-               radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+                       radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+                                                             &dig->dp_i2c_bus->adapter);
+               else if (radeon_connector->ddc_bus && !radeon_connector->edid)
+                       radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+                                                             &radeon_connector->ddc_bus->adapter);
+       } else {
+               if (radeon_connector->ddc_bus && !radeon_connector->edid)
+                       radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+                                                             &radeon_connector->ddc_bus->adapter);
        }
 
        if (!radeon_connector->edid) {
index b293487..319d85d 100644 (file)
@@ -2323,6 +2323,9 @@ radeon_add_atom_encoder(struct drm_device *dev,
        default:
                encoder->possible_crtcs = 0x3;
                break;
+       case 4:
+               encoder->possible_crtcs = 0xf;
+               break;
        case 6:
                encoder->possible_crtcs = 0x3f;
                break;
index d09031c..68820f5 100644 (file)
@@ -479,6 +479,7 @@ extern void radeon_dp_set_link_config(struct drm_connector *connector,
                                      struct drm_display_mode *mode);
 extern void radeon_dp_link_train(struct drm_encoder *encoder,
                                 struct drm_connector *connector);
+extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
 extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
 extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
 extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
index dee4a0c..602fa35 100644 (file)
@@ -40,10 +40,14 @@ void radeon_test_moves(struct radeon_device *rdev)
        size = 1024 * 1024;
 
        /* Number of tests =
-        * (Total GTT - IB pool - writeback page - ring buffer) / test size
+        * (Total GTT - IB pool - writeback page - ring buffers) / test size
         */
-       n = ((u32)(rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE -
-            rdev->cp.ring_size)) / size;
+       n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - rdev->cp.ring_size;
+       if (rdev->wb.wb_obj)
+               n -= RADEON_GPU_PAGE_SIZE;
+       if (rdev->ih.ring_obj)
+               n -= rdev->ih.ring_size;
+       n /= size;
 
        gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
        if (!gtt_obj) {
@@ -132,9 +136,15 @@ void radeon_test_moves(struct radeon_device *rdev)
                     gtt_start++, vram_start++) {
                        if (*vram_start != gtt_start) {
                                DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, "
-                                         "expected 0x%p (GTT map 0x%p-0x%p)\n",
-                                         i, *vram_start, gtt_start, gtt_map,
-                                         gtt_end);
+                                         "expected 0x%p (GTT/VRAM offset "
+                                         "0x%16llx/0x%16llx)\n",
+                                         i, *vram_start, gtt_start,
+                                         (unsigned long long)
+                                         (gtt_addr - rdev->mc.gtt_start +
+                                          (void*)gtt_start - gtt_map),
+                                         (unsigned long long)
+                                         (vram_addr - rdev->mc.vram_start +
+                                          (void*)gtt_start - gtt_map));
                                radeon_bo_kunmap(vram_obj);
                                goto out_cleanup;
                        }
@@ -175,9 +185,15 @@ void radeon_test_moves(struct radeon_device *rdev)
                     gtt_start++, vram_start++) {
                        if (*gtt_start != vram_start) {
                                DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, "
-                                         "expected 0x%p (VRAM map 0x%p-0x%p)\n",
-                                         i, *gtt_start, vram_start, vram_map,
-                                         vram_end);
+                                         "expected 0x%p (VRAM/GTT offset "
+                                         "0x%16llx/0x%16llx)\n",
+                                         i, *gtt_start, vram_start,
+                                         (unsigned long long)
+                                         (vram_addr - rdev->mc.vram_start +
+                                          (void*)vram_start - vram_map),
+                                         (unsigned long long)
+                                         (gtt_addr - rdev->mc.gtt_start +
+                                          (void*)vram_start - vram_map));
                                radeon_bo_kunmap(gtt_obj[i]);
                                goto out_cleanup;
                        }
index 60125dd..9b86fb0 100644 (file)
@@ -450,6 +450,29 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_
                        return -EINVAL;
                mem->bus.base = rdev->mc.aper_base;
                mem->bus.is_iomem = true;
+#ifdef __alpha__
+               /*
+                * Alpha: use bus.addr to hold the ioremap() return,
+                * so we can modify bus.base below.
+                */
+               if (mem->placement & TTM_PL_FLAG_WC)
+                       mem->bus.addr =
+                               ioremap_wc(mem->bus.base + mem->bus.offset,
+                                          mem->bus.size);
+               else
+                       mem->bus.addr =
+                               ioremap_nocache(mem->bus.base + mem->bus.offset,
+                                               mem->bus.size);
+
+               /*
+                * Alpha: Use just the bus offset plus
+                * the hose/domain memory base for bus.base.
+                * It then can be used to build PTEs for VRAM
+                * access, as done in ttm_bo_vm_fault().
+                */
+               mem->bus.base = (mem->bus.base & 0x0ffffffffUL) +
+                       rdev->ddev->hose->dense_mem_base;
+#endif
                break;
        default:
                return -EINVAL;
index 56619f6..a4d38d8 100644 (file)
@@ -353,8 +353,10 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
 
                ret = ttm_tt_set_user(bo->ttm, current,
                                      bo->buffer_start, bo->num_pages);
-               if (unlikely(ret != 0))
+               if (unlikely(ret != 0)) {
                        ttm_tt_destroy(bo->ttm);
+                       bo->ttm = NULL;
+               }
                break;
        default:
                printk(KERN_ERR TTM_PFX "Illegal buffer object type\n");
@@ -390,10 +392,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
         * Create and bind a ttm if required.
         */
 
-       if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm == NULL)) {
-               ret = ttm_bo_add_ttm(bo, false);
-               if (ret)
-                       goto out_err;
+       if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
+               if (bo->ttm == NULL) {
+                       ret = ttm_bo_add_ttm(bo, false);
+                       if (ret)
+                               goto out_err;
+               }
 
                ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement);
                if (ret)
index 77dbf40..ae3c6f5 100644 (file)
@@ -635,13 +635,13 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
                if (ret)
                        return ret;
 
-               ttm_bo_free_old_node(bo);
                if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
                    (bo->ttm != NULL)) {
                        ttm_tt_unbind(bo->ttm);
                        ttm_tt_destroy(bo->ttm);
                        bo->ttm = NULL;
                }
+               ttm_bo_free_old_node(bo);
        } else {
                /**
                 * This should help pipeline ordinary buffer moves.
index 306b15f..1130a89 100644 (file)
@@ -589,6 +589,7 @@ config HID_WACOM_POWER_SUPPLY
 config HID_WIIMOTE
        tristate "Nintendo Wii Remote support"
        depends on BT_HIDP
+       depends on LEDS_CLASS
        ---help---
        Support for the Nintendo Wii Remote bluetooth device.
 
index b85744f..18b3bc6 100644 (file)
@@ -444,6 +444,12 @@ static const struct hid_device_id apple_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
                        APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS),
+               .driver_data = APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
index 1a5cf0c..242353d 100644 (file)
@@ -1340,6 +1340,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
index db63ccf..7484e1b 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI   0x0245
 #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO    0x0246
 #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS    0x0247
+#define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI      0x024f
+#define USB_DEVICE_ID_APPLE_ALU_REVB_ISO       0x0250
+#define USB_DEVICE_ID_APPLE_ALU_REVB_JIS       0x0251
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
 #define USB_DEVICE_ID_PENPOWER         0x00f4
 
 #define USB_VENDOR_ID_GREENASIA                0x0e8f
+#define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD        0x3013
 
 #define USB_VENDOR_ID_GRETAGMACBETH    0x0971
 #define USB_DEVICE_ID_GRETAGMACBETH_HUEY       0x2005
 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE        0x0001
 #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE       0x0600
 
+#define USB_VENDOR_ID_SIGMA_MICRO      0x1c4f
+#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD     0x0002
+
 #define USB_VENDOR_ID_SKYCABLE                 0x1223
 #define        USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER       0x3F07
 
index 0ec91c1..f0fbd7b 100644 (file)
@@ -81,6 +81,28 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
 #define NO_TOUCHES -1
 #define SINGLE_TOUCH_UP -2
 
+/* Touch surface information. Dimension is in hundredths of a mm, min and max
+ * are in units. */
+#define MOUSE_DIMENSION_X (float)9056
+#define MOUSE_MIN_X -1100
+#define MOUSE_MAX_X 1258
+#define MOUSE_RES_X ((MOUSE_MAX_X - MOUSE_MIN_X) / (MOUSE_DIMENSION_X / 100))
+#define MOUSE_DIMENSION_Y (float)5152
+#define MOUSE_MIN_Y -1589
+#define MOUSE_MAX_Y 2047
+#define MOUSE_RES_Y ((MOUSE_MAX_Y - MOUSE_MIN_Y) / (MOUSE_DIMENSION_Y / 100))
+
+#define TRACKPAD_DIMENSION_X (float)13000
+#define TRACKPAD_MIN_X -2909
+#define TRACKPAD_MAX_X 3167
+#define TRACKPAD_RES_X \
+       ((TRACKPAD_MAX_X - TRACKPAD_MIN_X) / (TRACKPAD_DIMENSION_X / 100))
+#define TRACKPAD_DIMENSION_Y (float)11000
+#define TRACKPAD_MIN_Y -2456
+#define TRACKPAD_MAX_Y 2565
+#define TRACKPAD_RES_Y \
+       ((TRACKPAD_MAX_Y - TRACKPAD_MIN_Y) / (TRACKPAD_DIMENSION_Y / 100))
+
 /**
  * struct magicmouse_sc - Tracks Magic Mouse-specific data.
  * @input: Input device through which we report events.
@@ -406,17 +428,31 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h
                 * inverse of the reported Y.
                 */
                if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
-                       input_set_abs_params(input, ABS_MT_POSITION_X, -1100,
-                               1358, 4, 0);
-                       input_set_abs_params(input, ABS_MT_POSITION_Y, -1589,
-                               2047, 4, 0);
+                       input_set_abs_params(input, ABS_MT_POSITION_X,
+                               MOUSE_MIN_X, MOUSE_MAX_X, 4, 0);
+                       input_set_abs_params(input, ABS_MT_POSITION_Y,
+                               MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0);
+
+                       input_abs_set_res(input, ABS_MT_POSITION_X,
+                               MOUSE_RES_X);
+                       input_abs_set_res(input, ABS_MT_POSITION_Y,
+                               MOUSE_RES_Y);
                } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
-                       input_set_abs_params(input, ABS_X, -2909, 3167, 4, 0);
-                       input_set_abs_params(input, ABS_Y, -2456, 2565, 4, 0);
-                       input_set_abs_params(input, ABS_MT_POSITION_X, -2909,
-                               3167, 4, 0);
-                       input_set_abs_params(input, ABS_MT_POSITION_Y, -2456,
-                               2565, 4, 0);
+                       input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X,
+                               TRACKPAD_MAX_X, 4, 0);
+                       input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y,
+                               TRACKPAD_MAX_Y, 4, 0);
+                       input_set_abs_params(input, ABS_MT_POSITION_X,
+                               TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0);
+                       input_set_abs_params(input, ABS_MT_POSITION_Y,
+                               TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0);
+
+                       input_abs_set_res(input, ABS_X, TRACKPAD_RES_X);
+                       input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y);
+                       input_abs_set_res(input, ABS_MT_POSITION_X,
+                               TRACKPAD_RES_X);
+                       input_abs_set_res(input, ABS_MT_POSITION_Y,
+                               TRACKPAD_RES_Y);
                }
 
                input_set_events_per_packet(input, 60);
@@ -501,9 +537,17 @@ static int magicmouse_probe(struct hid_device *hdev,
        }
        report->size = 6;
 
+       /*
+        * Some devices repond with 'invalid report id' when feature
+        * report switching it into multitouch mode is sent to it.
+        *
+        * This results in -EIO from the _raw low-level transport callback,
+        * but there seems to be no other way of switching the mode.
+        * Thus the super-ugly hacky success check below.
+        */
        ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
                        HID_FEATURE_REPORT);
-       if (ret != sizeof(feature)) {
+       if (ret != -EIO && ret != sizeof(feature)) {
                hid_err(hdev, "unable to request touch data (%d)\n", ret);
                goto err_stop_hw;
        }
index 0688832..a597039 100644 (file)
@@ -353,11 +353,7 @@ static int wacom_probe(struct hid_device *hdev,
        if (ret) {
                hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
                         ret);
-               /*
-                * battery attribute is not critical for the tablet, but if it
-                * failed then there is no need to create ac attribute
-                */
-               goto move_on;
+               goto err_battery;
        }
 
        wdata->ac.properties = wacom_ac_props;
@@ -371,14 +367,8 @@ static int wacom_probe(struct hid_device *hdev,
        if (ret) {
                hid_warn(hdev,
                         "can't create ac battery attribute, err: %d\n", ret);
-               /*
-                * ac attribute is not critical for the tablet, but if it
-                * failed then we don't want to battery attribute to exist
-                */
-               power_supply_unregister(&wdata->battery);
+               goto err_ac;
        }
-
-move_on:
 #endif
        hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
        input = hidinput->input;
@@ -416,6 +406,13 @@ move_on:
 
        return 0;
 
+#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
+err_ac:
+       power_supply_unregister(&wdata->battery);
+err_battery:
+       device_remove_file(&hdev->dev, &dev_attr_speed);
+       hid_hw_stop(hdev);
+#endif
 err_free:
        kfree(wdata);
        return ret;
@@ -426,6 +423,7 @@ static void wacom_remove(struct hid_device *hdev)
 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
        struct wacom_data *wdata = hid_get_drvdata(hdev);
 #endif
+       device_remove_file(&hdev->dev, &dev_attr_speed);
        hid_hw_stop(hdev);
 
 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
index a594383..85a02e5 100644 (file)
  * any later version.
  */
 
-#include <linux/atomic.h>
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/input.h>
+#include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include "hid-ids.h"
@@ -33,9 +33,9 @@ struct wiimote_state {
 };
 
 struct wiimote_data {
-       atomic_t ready;
        struct hid_device *hdev;
        struct input_dev *input;
+       struct led_classdev *leds[4];
 
        spinlock_t qlock;
        __u8 head;
@@ -53,8 +53,15 @@ struct wiimote_data {
 #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
                                        WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
 
+/* return flag for led \num */
+#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1))
+
 enum wiiproto_reqs {
+       WIIPROTO_REQ_NULL = 0x0,
        WIIPROTO_REQ_LED = 0x11,
+       WIIPROTO_REQ_DRM = 0x12,
+       WIIPROTO_REQ_STATUS = 0x20,
+       WIIPROTO_REQ_RETURN = 0x22,
        WIIPROTO_REQ_DRM_K = 0x30,
 };
 
@@ -87,9 +94,6 @@ static __u16 wiiproto_keymap[] = {
        BTN_MODE,       /* WIIPROTO_KEY_HOME */
 };
 
-#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \
-                                                                       dev))
-
 static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
                                                                size_t count)
 {
@@ -192,66 +196,96 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
        wiimote_queue(wdata, cmd, sizeof(cmd));
 }
 
-#define wiifs_led_show_set(num)                                                \
-static ssize_t wiifs_led_show_##num(struct device *dev,                        \
-                       struct device_attribute *attr, char *buf)       \
-{                                                                      \
-       struct wiimote_data *wdata = dev_to_wii(dev);                   \
-       unsigned long flags;                                            \
-       int state;                                                      \
-                                                                       \
-       if (!atomic_read(&wdata->ready))                                \
-               return -EBUSY;                                          \
-                                                                       \
-       spin_lock_irqsave(&wdata->state.lock, flags);                   \
-       state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num);        \
-       spin_unlock_irqrestore(&wdata->state.lock, flags);              \
-                                                                       \
-       return sprintf(buf, "%d\n", state);                             \
-}                                                                      \
-static ssize_t wiifs_led_set_##num(struct device *dev,                 \
-       struct device_attribute *attr, const char *buf, size_t count)   \
-{                                                                      \
-       struct wiimote_data *wdata = dev_to_wii(dev);                   \
-       int tmp = simple_strtoul(buf, NULL, 10);                        \
-       unsigned long flags;                                            \
-       __u8 state;                                                     \
-                                                                       \
-       if (!atomic_read(&wdata->ready))                                \
-               return -EBUSY;                                          \
-                                                                       \
-       spin_lock_irqsave(&wdata->state.lock, flags);                   \
-                                                                       \
-       state = wdata->state.flags;                                     \
-                                                                       \
-       if (tmp)                                                        \
-               wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\
-       else                                                            \
-               wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\
-                                                                       \
-       spin_unlock_irqrestore(&wdata->state.lock, flags);              \
-                                                                       \
-       return count;                                                   \
-}                                                                      \
-static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num,  \
-                                               wiifs_led_set_##num)
-
-wiifs_led_show_set(1);
-wiifs_led_show_set(2);
-wiifs_led_show_set(3);
-wiifs_led_show_set(4);
+/*
+ * Check what peripherals of the wiimote are currently
+ * active and select a proper DRM that supports all of
+ * the requested data inputs.
+ */
+static __u8 select_drm(struct wiimote_data *wdata)
+{
+       return WIIPROTO_REQ_DRM_K;
+}
+
+static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
+{
+       __u8 cmd[3];
+
+       if (drm == WIIPROTO_REQ_NULL)
+               drm = select_drm(wdata);
+
+       cmd[0] = WIIPROTO_REQ_DRM;
+       cmd[1] = 0;
+       cmd[2] = drm;
+
+       wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev)
+{
+       struct wiimote_data *wdata;
+       struct device *dev = led_dev->dev->parent;
+       int i;
+       unsigned long flags;
+       bool value = false;
+
+       wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
+
+       for (i = 0; i < 4; ++i) {
+               if (wdata->leds[i] == led_dev) {
+                       spin_lock_irqsave(&wdata->state.lock, flags);
+                       value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1);
+                       spin_unlock_irqrestore(&wdata->state.lock, flags);
+                       break;
+               }
+       }
+
+       return value ? LED_FULL : LED_OFF;
+}
+
+static void wiimote_leds_set(struct led_classdev *led_dev,
+                                               enum led_brightness value)
+{
+       struct wiimote_data *wdata;
+       struct device *dev = led_dev->dev->parent;
+       int i;
+       unsigned long flags;
+       __u8 state, flag;
+
+       wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
+
+       for (i = 0; i < 4; ++i) {
+               if (wdata->leds[i] == led_dev) {
+                       flag = WIIPROTO_FLAG_LED(i + 1);
+                       spin_lock_irqsave(&wdata->state.lock, flags);
+                       state = wdata->state.flags;
+                       if (value == LED_OFF)
+                               wiiproto_req_leds(wdata, state & ~flag);
+                       else
+                               wiiproto_req_leds(wdata, state | flag);
+                       spin_unlock_irqrestore(&wdata->state.lock, flags);
+                       break;
+               }
+       }
+}
 
 static int wiimote_input_event(struct input_dev *dev, unsigned int type,
                                                unsigned int code, int value)
+{
+       return 0;
+}
+
+static int wiimote_input_open(struct input_dev *dev)
 {
        struct wiimote_data *wdata = input_get_drvdata(dev);
 
-       if (!atomic_read(&wdata->ready))
-               return -EBUSY;
-       /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */
-       smp_rmb();
+       return hid_hw_open(wdata->hdev);
+}
 
-       return 0;
+static void wiimote_input_close(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+
+       hid_hw_close(wdata->hdev);
 }
 
 static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
@@ -281,6 +315,26 @@ static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
        input_sync(wdata->input);
 }
 
+static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
+{
+       handler_keys(wdata, payload);
+
+       /* on status reports the drm is reset so we need to resend the drm */
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+}
+
+static void handler_return(struct wiimote_data *wdata, const __u8 *payload)
+{
+       __u8 err = payload[3];
+       __u8 cmd = payload[2];
+
+       handler_keys(wdata, payload);
+
+       if (err)
+               hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err,
+                                                                       cmd);
+}
+
 struct wiiproto_handler {
        __u8 id;
        size_t size;
@@ -288,6 +342,8 @@ struct wiiproto_handler {
 };
 
 static struct wiiproto_handler handlers[] = {
+       { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status },
+       { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return },
        { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
        { .id = 0 }
 };
@@ -300,11 +356,6 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
        int i;
        unsigned long flags;
 
-       if (!atomic_read(&wdata->ready))
-               return -EBUSY;
-       /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */
-       smp_rmb();
-
        if (size < 1)
                return -EINVAL;
 
@@ -321,6 +372,58 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
        return 0;
 }
 
+static void wiimote_leds_destroy(struct wiimote_data *wdata)
+{
+       int i;
+       struct led_classdev *led;
+
+       for (i = 0; i < 4; ++i) {
+               if (wdata->leds[i]) {
+                       led = wdata->leds[i];
+                       wdata->leds[i] = NULL;
+                       led_classdev_unregister(led);
+                       kfree(led);
+               }
+       }
+}
+
+static int wiimote_leds_create(struct wiimote_data *wdata)
+{
+       int i, ret;
+       struct device *dev = &wdata->hdev->dev;
+       size_t namesz = strlen(dev_name(dev)) + 9;
+       struct led_classdev *led;
+       char *name;
+
+       for (i = 0; i < 4; ++i) {
+               led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL);
+               if (!led) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+               name = (void*)&led[1];
+               snprintf(name, namesz, "%s:blue:p%d", dev_name(dev), i);
+               led->name = name;
+               led->brightness = 0;
+               led->max_brightness = 1;
+               led->brightness_get = wiimote_leds_get;
+               led->brightness_set = wiimote_leds_set;
+
+               ret = led_classdev_register(dev, led);
+               if (ret) {
+                       kfree(led);
+                       goto err;
+               }
+               wdata->leds[i] = led;
+       }
+
+       return 0;
+
+err:
+       wiimote_leds_destroy(wdata);
+       return ret;
+}
+
 static struct wiimote_data *wiimote_create(struct hid_device *hdev)
 {
        struct wiimote_data *wdata;
@@ -341,6 +444,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
 
        input_set_drvdata(wdata->input, wdata);
        wdata->input->event = wiimote_input_event;
+       wdata->input->open = wiimote_input_open;
+       wdata->input->close = wiimote_input_close;
        wdata->input->dev.parent = &wdata->hdev->dev;
        wdata->input->id.bustype = wdata->hdev->bus;
        wdata->input->id.vendor = wdata->hdev->vendor;
@@ -362,6 +467,12 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
 
 static void wiimote_destroy(struct wiimote_data *wdata)
 {
+       wiimote_leds_destroy(wdata);
+
+       input_unregister_device(wdata->input);
+       cancel_work_sync(&wdata->worker);
+       hid_hw_stop(wdata->hdev);
+
        kfree(wdata);
 }
 
@@ -377,19 +488,6 @@ static int wiimote_hid_probe(struct hid_device *hdev,
                return -ENOMEM;
        }
 
-       ret = device_create_file(&hdev->dev, &dev_attr_led1);
-       if (ret)
-               goto err;
-       ret = device_create_file(&hdev->dev, &dev_attr_led2);
-       if (ret)
-               goto err;
-       ret = device_create_file(&hdev->dev, &dev_attr_led3);
-       if (ret)
-               goto err;
-       ret = device_create_file(&hdev->dev, &dev_attr_led4);
-       if (ret)
-               goto err;
-
        ret = hid_parse(hdev);
        if (ret) {
                hid_err(hdev, "HID parse failed\n");
@@ -408,9 +506,10 @@ static int wiimote_hid_probe(struct hid_device *hdev,
                goto err_stop;
        }
 
-       /* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */
-       smp_wmb();
-       atomic_set(&wdata->ready, 1);
+       ret = wiimote_leds_create(wdata);
+       if (ret)
+               goto err_free;
+
        hid_info(hdev, "New device registered\n");
 
        /* by default set led1 after device initialization */
@@ -420,15 +519,15 @@ static int wiimote_hid_probe(struct hid_device *hdev,
 
        return 0;
 
+err_free:
+       wiimote_destroy(wdata);
+       return ret;
+
 err_stop:
        hid_hw_stop(hdev);
 err:
        input_free_device(wdata->input);
-       device_remove_file(&hdev->dev, &dev_attr_led1);
-       device_remove_file(&hdev->dev, &dev_attr_led2);
-       device_remove_file(&hdev->dev, &dev_attr_led3);
-       device_remove_file(&hdev->dev, &dev_attr_led4);
-       wiimote_destroy(wdata);
+       kfree(wdata);
        return ret;
 }
 
@@ -437,16 +536,6 @@ static void wiimote_hid_remove(struct hid_device *hdev)
        struct wiimote_data *wdata = hid_get_drvdata(hdev);
 
        hid_info(hdev, "Device removed\n");
-
-       device_remove_file(&hdev->dev, &dev_attr_led1);
-       device_remove_file(&hdev->dev, &dev_attr_led2);
-       device_remove_file(&hdev->dev, &dev_attr_led3);
-       device_remove_file(&hdev->dev, &dev_attr_led4);
-
-       hid_hw_stop(hdev);
-       input_unregister_device(wdata->input);
-
-       cancel_work_sync(&wdata->worker);
        wiimote_destroy(wdata);
 }
 
index 621959d..3146fdc 100644 (file)
@@ -47,6 +47,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL },
 
        { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
        { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT },
@@ -89,6 +90,7 @@ static const struct hid_blacklist {
 
        { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS },
        { 0, 0 }
 };
 
index c4c40be..d22f241 100644 (file)
@@ -114,7 +114,6 @@ struct i5k_amb_data {
        void __iomem *amb_mmio;
        struct i5k_device_attribute *attrs;
        unsigned int num_attrs;
-       unsigned long chipset_id;
 };
 
 static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
@@ -444,8 +443,6 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data,
                goto out;
        }
 
-       data->chipset_id = devid;
-
        res = 0;
 out:
        pci_dev_put(pcidev);
@@ -478,23 +475,13 @@ out:
        return res;
 }
 
-static unsigned long i5k_channel_pci_id(struct i5k_amb_data *data,
-                                       unsigned long channel)
-{
-       switch (data->chipset_id) {
-       case PCI_DEVICE_ID_INTEL_5000_ERR:
-               return PCI_DEVICE_ID_INTEL_5000_FBD0 + channel;
-       case PCI_DEVICE_ID_INTEL_5400_ERR:
-               return PCI_DEVICE_ID_INTEL_5400_FBD0 + channel;
-       default:
-               BUG();
-       }
-}
-
-static unsigned long chipset_ids[] = {
-       PCI_DEVICE_ID_INTEL_5000_ERR,
-       PCI_DEVICE_ID_INTEL_5400_ERR,
-       0
+static struct {
+       unsigned long err;
+       unsigned long fbd0;
+} chipset_ids[] __devinitdata  = {
+       { PCI_DEVICE_ID_INTEL_5000_ERR, PCI_DEVICE_ID_INTEL_5000_FBD0 },
+       { PCI_DEVICE_ID_INTEL_5400_ERR, PCI_DEVICE_ID_INTEL_5400_FBD0 },
+       { 0, 0 }
 };
 
 #ifdef MODULE
@@ -510,8 +497,7 @@ static int __devinit i5k_amb_probe(struct platform_device *pdev)
 {
        struct i5k_amb_data *data;
        struct resource *reso;
-       int i;
-       int res = -ENODEV;
+       int i, res;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
@@ -520,22 +506,22 @@ static int __devinit i5k_amb_probe(struct platform_device *pdev)
        /* Figure out where the AMB registers live */
        i = 0;
        do {
-               res = i5k_find_amb_registers(data, chipset_ids[i]);
+               res = i5k_find_amb_registers(data, chipset_ids[i].err);
+               if (res == 0)
+                       break;
                i++;
-       } while (res && chipset_ids[i]);
+       } while (chipset_ids[i].err);
 
        if (res)
                goto err;
 
        /* Copy the DIMM presence map for the first two channels */
-       res = i5k_channel_probe(&data->amb_present[0],
-                               i5k_channel_pci_id(data, 0));
+       res = i5k_channel_probe(&data->amb_present[0], chipset_ids[i].fbd0);
        if (res)
                goto err;
 
        /* Copy the DIMM presence map for the optional second two channels */
-       i5k_channel_probe(&data->amb_present[2],
-                         i5k_channel_pci_id(data, 1));
+       i5k_channel_probe(&data->amb_present[2], chipset_ids[i].fbd0 + 1);
 
        /* Set up resource regions */
        reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME);
index 1a409c5..c316294 100644 (file)
@@ -432,13 +432,15 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
        aem_send_message(ipmi);
 
        res = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT);
-       if (!res)
-               return -ETIMEDOUT;
+       if (!res) {
+               res = -ETIMEDOUT;
+               goto out;
+       }
 
        if (ipmi->rx_result || ipmi->rx_msg_len != rs_size ||
            memcmp(&rs_resp->id, &system_x_id, sizeof(system_x_id))) {
-               kfree(rs_resp);
-               return -ENOENT;
+               res = -ENOENT;
+               goto out;
        }
 
        switch (size) {
@@ -463,8 +465,11 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
                break;
        }
        }
+       res = 0;
 
-       return 0;
+out:
+       kfree(rs_resp);
+       return res;
 }
 
 /* Update AEM energy registers */
index d94a24f..dd2d7b9 100644 (file)
@@ -124,7 +124,7 @@ static inline int MV_TO_LIMIT(int mv, int range)
 
 static inline int ADC_TO_CURR(int adc, int gain)
 {
-       return adc * 1400000 / gain * 255;
+       return adc * 1400000 / (gain * 255);
 }
 
 /*
index d7926f4..eab1161 100644 (file)
@@ -211,8 +211,7 @@ static int lookup_comp(struct ntc_data *data,
        if (data->comp[mid].ohm <= ohm) {
                *i_low = mid;
                *i_high = mid - 1;
-       }
-       if (data->comp[mid].ohm > ohm) {
+       } else {
                *i_low = mid + 1;
                *i_high = mid;
        }
index d4bc114..ac254fb 100644 (file)
@@ -161,6 +161,17 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
        return ret;
 }
 
+static int lm25066_write_byte(struct i2c_client *client, int page, u8 value)
+{
+       if (page > 1)
+               return -EINVAL;
+
+       if (page == 0)
+               return pmbus_write_byte(client, 0, value);
+
+       return 0;
+}
+
 static int lm25066_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
@@ -204,6 +215,7 @@ static int lm25066_probe(struct i2c_client *client,
 
        info->read_word_data = lm25066_read_word_data;
        info->write_word_data = lm25066_write_word_data;
+       info->write_byte = lm25066_write_byte;
 
        switch (id->driver_data) {
        case lm25066:
index 0808d98..a6ae20f 100644 (file)
@@ -325,6 +325,7 @@ struct pmbus_driver_info {
        int (*read_word_data)(struct i2c_client *client, int page, int reg);
        int (*write_word_data)(struct i2c_client *client, int page, int reg,
                               u16 word);
+       int (*write_byte)(struct i2c_client *client, int page, u8 value);
        /*
         * The identify function determines supported PMBus functionality.
         * This function is only necessary if a chip driver supports multiple
index 5c1b6cf..a561c3a 100644 (file)
@@ -182,6 +182,24 @@ int pmbus_write_byte(struct i2c_client *client, int page, u8 value)
 }
 EXPORT_SYMBOL_GPL(pmbus_write_byte);
 
+/*
+ * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if
+ * a device specific mapping funcion exists and calls it if necessary.
+ */
+static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value)
+{
+       struct pmbus_data *data = i2c_get_clientdata(client);
+       const struct pmbus_driver_info *info = data->info;
+       int status;
+
+       if (info->write_byte) {
+               status = info->write_byte(client, page, value);
+               if (status != -ENODATA)
+                       return status;
+       }
+       return pmbus_write_byte(client, page, value);
+}
+
 int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word)
 {
        int rv;
@@ -281,7 +299,7 @@ static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg)
 
 static void pmbus_clear_fault_page(struct i2c_client *client, int page)
 {
-       pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
+       _pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
 }
 
 void pmbus_clear_faults(struct i2c_client *client)
index ace1c73..d0ddb60 100644 (file)
@@ -141,13 +141,11 @@ static int ucd9000_probe(struct i2c_client *client,
        block_buffer[ret] = '\0';
        dev_info(&client->dev, "Device ID %s\n", block_buffer);
 
-       mid = NULL;
-       for (i = 0; i < ARRAY_SIZE(ucd9000_id); i++) {
-               mid = &ucd9000_id[i];
+       for (mid = ucd9000_id; mid->name[0]; mid++) {
                if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
                        break;
        }
-       if (!mid || !strlen(mid->name)) {
+       if (!mid->name[0]) {
                dev_err(&client->dev, "Unsupported device\n");
                return -ENODEV;
        }
index ffcc1cf..c65e9da 100644 (file)
@@ -68,13 +68,11 @@ static int ucd9200_probe(struct i2c_client *client,
        block_buffer[ret] = '\0';
        dev_info(&client->dev, "Device ID %s\n", block_buffer);
 
-       mid = NULL;
-       for (i = 0; i < ARRAY_SIZE(ucd9200_id); i++) {
-               mid = &ucd9200_id[i];
+       for (mid = ucd9200_id; mid->name[0]; mid++) {
                if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
                        break;
        }
-       if (!mid || !strlen(mid->name)) {
+       if (!mid->name[0]) {
                dev_err(&client->dev, "Unsupported device\n");
                return -ENODEV;
        }
index 0c731ca..b228e09 100644 (file)
@@ -146,6 +146,7 @@ struct i2c_nmk_client {
  * @stop: stop condition
  * @xfer_complete: acknowledge completion for a I2C message
  * @result: controller propogated result
+ * @regulator: pointer to i2c regulator
  * @busy: Busy doing transfer
  */
 struct nmk_i2c_dev {
@@ -417,12 +418,12 @@ static int read_i2c(struct nmk_i2c_dev *dev)
        writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
                        dev->virtbase + I2C_IMSCR);
 
-       timeout = wait_for_completion_interruptible_timeout(
+       timeout = wait_for_completion_timeout(
                &dev->xfer_complete, dev->adap.timeout);
 
        if (timeout < 0) {
                dev_err(&dev->pdev->dev,
-                       "wait_for_completion_interruptible_timeout"
+                       "wait_for_completion_timeout"
                        "returned %d waiting for event\n", timeout);
                status = timeout;
        }
@@ -504,12 +505,12 @@ static int write_i2c(struct nmk_i2c_dev *dev)
        writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
                        dev->virtbase + I2C_IMSCR);
 
-       timeout = wait_for_completion_interruptible_timeout(
+       timeout = wait_for_completion_timeout(
                &dev->xfer_complete, dev->adap.timeout);
 
        if (timeout < 0) {
                dev_err(&dev->pdev->dev,
-                       "wait_for_completion_interruptible_timeout"
+                       "wait_for_completion_timeout "
                        "returned %d waiting for event\n", timeout);
                status = timeout;
        }
index 1a766cf..2dfb631 100644 (file)
@@ -1139,41 +1139,12 @@ omap_i2c_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_SUSPEND
-static int omap_i2c_suspend(struct device *dev)
-{
-       if (!pm_runtime_suspended(dev))
-               if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend)
-                       dev->bus->pm->runtime_suspend(dev);
-
-       return 0;
-}
-
-static int omap_i2c_resume(struct device *dev)
-{
-       if (!pm_runtime_suspended(dev))
-               if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume)
-                       dev->bus->pm->runtime_resume(dev);
-
-       return 0;
-}
-
-static struct dev_pm_ops omap_i2c_pm_ops = {
-       .suspend = omap_i2c_suspend,
-       .resume = omap_i2c_resume,
-};
-#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
-#else
-#define OMAP_I2C_PM_OPS NULL
-#endif
-
 static struct platform_driver omap_i2c_driver = {
        .probe          = omap_i2c_probe,
        .remove         = omap_i2c_remove,
        .driver         = {
                .name   = "omap_i2c",
                .owner  = THIS_MODULE,
-               .pm     = OMAP_I2C_PM_OPS,
        },
 };
 
index 6659d26..b73da6c 100644 (file)
@@ -109,12 +109,15 @@ static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
                return -EINVAL;
        }
        sds = kzalloc(sizeof(*sds), GFP_KERNEL);
-       if (!sds)
+       if (!sds) {
+               ret = -ENOMEM;
                goto err_mem;
+       }
 
        for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
                sds->pdev[i] = add_i2c_device(dev, i);
                if (IS_ERR(sds->pdev[i])) {
+                       ret = PTR_ERR(sds->pdev[i]);
                        while (--i >= 0)
                                platform_device_unregister(sds->pdev[i]);
                        goto err_dev_add;
index 2440b74..3c94c4a 100644 (file)
@@ -270,14 +270,30 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
 
        /* Rounds down to not include partial word at the end of buf */
        words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
-       if (words_to_transfer > tx_fifo_avail)
-               words_to_transfer = tx_fifo_avail;
 
-       i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
-
-       buf += words_to_transfer * BYTES_PER_FIFO_WORD;
-       buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
-       tx_fifo_avail -= words_to_transfer;
+       /* It's very common to have < 4 bytes, so optimize that case. */
+       if (words_to_transfer) {
+               if (words_to_transfer > tx_fifo_avail)
+                       words_to_transfer = tx_fifo_avail;
+
+               /*
+                * Update state before writing to FIFO.  If this casues us
+                * to finish writing all bytes (AKA buf_remaining goes to 0) we
+                * have a potential for an interrupt (PACKET_XFER_COMPLETE is
+                * not maskable).  We need to make sure that the isr sees
+                * buf_remaining as 0 and doesn't call us back re-entrantly.
+                */
+               buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
+               tx_fifo_avail -= words_to_transfer;
+               i2c_dev->msg_buf_remaining = buf_remaining;
+               i2c_dev->msg_buf = buf +
+                       words_to_transfer * BYTES_PER_FIFO_WORD;
+               barrier();
+
+               i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
+
+               buf += words_to_transfer * BYTES_PER_FIFO_WORD;
+       }
 
        /*
         * If there is a partial word at the end of buf, handle it manually to
@@ -287,14 +303,15 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
        if (tx_fifo_avail > 0 && buf_remaining > 0) {
                BUG_ON(buf_remaining > 3);
                memcpy(&val, buf, buf_remaining);
+
+               /* Again update before writing to FIFO to make sure isr sees. */
+               i2c_dev->msg_buf_remaining = 0;
+               i2c_dev->msg_buf = NULL;
+               barrier();
+
                i2c_writel(i2c_dev, val, I2C_TX_FIFO);
-               buf_remaining = 0;
-               tx_fifo_avail--;
        }
 
-       BUG_ON(tx_fifo_avail > 0 && buf_remaining > 0);
-       i2c_dev->msg_buf_remaining = buf_remaining;
-       i2c_dev->msg_buf = buf;
        return 0;
 }
 
@@ -411,9 +428,10 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
                        tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ);
        }
 
-       if ((status & I2C_INT_PACKET_XFER_COMPLETE) &&
-                       !i2c_dev->msg_buf_remaining)
+       if (status & I2C_INT_PACKET_XFER_COMPLETE) {
+               BUG_ON(i2c_dev->msg_buf_remaining);
                complete(&i2c_dev->msg_complete);
+       }
 
        i2c_writel(i2c_dev, status, I2C_INT_STATUS);
        if (i2c_dev->is_dvc)
@@ -531,7 +549,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 
 static u32 tegra_i2c_func(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_I2C;
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
 static const struct i2c_algorithm tegra_i2c_algo = {
@@ -719,6 +737,17 @@ static int tegra_i2c_resume(struct platform_device *pdev)
 }
 #endif
 
+#if defined(CONFIG_OF)
+/* Match table for of_platform binding */
+static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
+       { .compatible = "nvidia,tegra20-i2c", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
+#else
+#define tegra_i2c_of_match NULL
+#endif
+
 static struct platform_driver tegra_i2c_driver = {
        .probe   = tegra_i2c_probe,
        .remove  = tegra_i2c_remove,
@@ -729,6 +758,7 @@ static struct platform_driver tegra_i2c_driver = {
        .driver  = {
                .name  = "tegra-i2c",
                .owner = THIS_MODULE,
+               .of_match_table = tegra_i2c_of_match,
        },
 };
 
index 43f89ba..fe89c46 100644 (file)
@@ -717,11 +717,13 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_neigh *neigh;
-       struct neighbour *n;
+       struct neighbour *n = NULL;
        unsigned long flags;
 
-       n = dst_get_neighbour(skb_dst(skb));
-       if (likely(skb_dst(skb) && n)) {
+       if (likely(skb_dst(skb)))
+               n = dst_get_neighbour(skb_dst(skb));
+
+       if (likely(n)) {
                if (unlikely(!*to_ipoib_neigh(n))) {
                        ipoib_path_lookup(skb, dev);
                        return NETDEV_TX_OK;
index 8db008d..9c61b9c 100644 (file)
@@ -101,13 +101,17 @@ iscsi_iser_recv(struct iscsi_conn *conn,
 
        /* verify PDU length */
        datalen = ntoh24(hdr->dlength);
-       if (datalen != rx_data_len) {
-               printk(KERN_ERR "iscsi_iser: datalen %d (hdr) != %d (IB) \n",
-                      datalen, rx_data_len);
+       if (datalen > rx_data_len || (datalen + 4) < rx_data_len) {
+               iser_err("wrong datalen %d (hdr), %d (IB)\n",
+                       datalen, rx_data_len);
                rc = ISCSI_ERR_DATALEN;
                goto error;
        }
 
+       if (datalen != rx_data_len)
+               iser_dbg("aligned datalen (%d) hdr, %d (IB)\n",
+                       datalen, rx_data_len);
+
        /* read AHS */
        ahslen = hdr->hlength * 4;
 
index 342cbc1..db6f3ce 100644 (file)
@@ -89,7 +89,7 @@
        } while (0)
 
 #define SHIFT_4K       12
-#define SIZE_4K        (1UL << SHIFT_4K)
+#define SIZE_4K        (1ULL << SHIFT_4K)
 #define MASK_4K        (~(SIZE_4K-1))
 
                                        /* support up to 512KB in one RDMA */
index 5745b7f..f299de6 100644 (file)
@@ -412,7 +412,7 @@ int iser_send_control(struct iscsi_conn *conn,
                memcpy(iser_conn->ib_conn->login_buf, task->data,
                                                        task->data_count);
                tx_dsg->addr    = iser_conn->ib_conn->login_dma;
-               tx_dsg->length  = data_seg_len;
+               tx_dsg->length  = task->data_count;
                tx_dsg->lkey    = device->mr->lkey;
                mdesc->num_sge = 2;
        }
index 9882971..358cd7e 100644 (file)
@@ -139,7 +139,7 @@ struct analog_port {
 #include <linux/i8253.h>
 
 #define GET_TIME(x)    do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
-#define DELTA(x,y)     (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0)))
+#define DELTA(x,y)     (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0)))
 #define TIME_NAME      (cpu_has_tsc?"TSC":"PIT")
 static unsigned int get_time_pit(void)
 {
index c8242dd..aa17e02 100644 (file)
@@ -20,6 +20,7 @@
  * flag.
  */
 
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
index f270447..a5a7791 100644 (file)
@@ -702,7 +702,7 @@ err_iounmap:
 err_free_mem_region:
        release_mem_region(res->start, resource_size(res));
 err_free_mem:
-       input_free_device(kbc->idev);
+       input_free_device(input_dev);
        kfree(kbc);
 
        return err;
index e21deb1..025417d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * AD714X CapTouch Programmable Controller driver (I2C bus)
  *
- * Copyright 2009 Analog Devices Inc.
+ * Copyright 2009-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -27,54 +27,49 @@ static int ad714x_i2c_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume);
 
-static int ad714x_i2c_write(struct device *dev, unsigned short reg,
-                               unsigned short data)
+static int ad714x_i2c_write(struct ad714x_chip *chip,
+                           unsigned short reg, unsigned short data)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       int ret = 0;
-       u8 *_reg = (u8 *)&reg;
-       u8 *_data = (u8 *)&data;
-
-       u8 tx[4] = {
-               _reg[1],
-               _reg[0],
-               _data[1],
-               _data[0]
-       };
-
-       ret = i2c_master_send(client, tx, 4);
-       if (ret < 0)
-               dev_err(&client->dev, "I2C write error\n");
-
-       return ret;
+       struct i2c_client *client = to_i2c_client(chip->dev);
+       int error;
+
+       chip->xfer_buf[0] = cpu_to_be16(reg);
+       chip->xfer_buf[1] = cpu_to_be16(data);
+
+       error = i2c_master_send(client, (u8 *)chip->xfer_buf,
+                               2 * sizeof(*chip->xfer_buf));
+       if (unlikely(error < 0)) {
+               dev_err(&client->dev, "I2C write error: %d\n", error);
+               return error;
+       }
+
+       return 0;
 }
 
-static int ad714x_i2c_read(struct device *dev, unsigned short reg,
-                               unsigned short *data)
+static int ad714x_i2c_read(struct ad714x_chip *chip,
+                          unsigned short reg, unsigned short *data, size_t len)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       int ret = 0;
-       u8 *_reg = (u8 *)&reg;
-       u8 *_data = (u8 *)data;
-
-       u8 tx[2] = {
-               _reg[1],
-               _reg[0]
-       };
-       u8 rx[2];
-
-       ret = i2c_master_send(client, tx, 2);
-       if (ret >= 0)
-               ret = i2c_master_recv(client, rx, 2);
-
-       if (unlikely(ret < 0)) {
-               dev_err(&client->dev, "I2C read error\n");
-       } else {
-               _data[0] = rx[1];
-               _data[1] = rx[0];
+       struct i2c_client *client = to_i2c_client(chip->dev);
+       int i;
+       int error;
+
+       chip->xfer_buf[0] = cpu_to_be16(reg);
+
+       error = i2c_master_send(client, (u8 *)chip->xfer_buf,
+                               sizeof(*chip->xfer_buf));
+       if (error >= 0)
+               error = i2c_master_recv(client, (u8 *)chip->xfer_buf,
+                                       len * sizeof(*chip->xfer_buf));
+
+       if (unlikely(error < 0)) {
+               dev_err(&client->dev, "I2C read error: %d\n", error);
+               return error;
        }
 
-       return ret;
+       for (i = 0; i < len; i++)
+               data[i] = be16_to_cpu(chip->xfer_buf[i]);
+
+       return 0;
 }
 
 static int __devinit ad714x_i2c_probe(struct i2c_client *client,
index 4120dd5..875b508 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * AD714X CapTouch Programmable Controller driver (SPI bus)
  *
- * Copyright 2009 Analog Devices Inc.
+ * Copyright 2009-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/input.h>       /* BUS_I2C */
+#include <linux/input.h>       /* BUS_SPI */
 #include <linux/module.h>
 #include <linux/spi/spi.h>
 #include <linux/pm.h>
@@ -30,30 +30,68 @@ static int ad714x_spi_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume);
 
-static int ad714x_spi_read(struct device *dev, unsigned short reg,
-               unsigned short *data)
+static int ad714x_spi_read(struct ad714x_chip *chip,
+                          unsigned short reg, unsigned short *data, size_t len)
 {
-       struct spi_device *spi = to_spi_device(dev);
-       unsigned short tx = AD714x_SPI_CMD_PREFIX | AD714x_SPI_READ | reg;
+       struct spi_device *spi = to_spi_device(chip->dev);
+       struct spi_message message;
+       struct spi_transfer xfer[2];
+       int i;
+       int error;
+
+       spi_message_init(&message);
+       memset(xfer, 0, sizeof(xfer));
+
+       chip->xfer_buf[0] = cpu_to_be16(AD714x_SPI_CMD_PREFIX |
+                                       AD714x_SPI_READ | reg);
+       xfer[0].tx_buf = &chip->xfer_buf[0];
+       xfer[0].len = sizeof(chip->xfer_buf[0]);
+       spi_message_add_tail(&xfer[0], &message);
+
+       xfer[1].rx_buf = &chip->xfer_buf[1];
+       xfer[1].len = sizeof(chip->xfer_buf[1]) * len;
+       spi_message_add_tail(&xfer[1], &message);
+
+       error = spi_sync(spi, &message);
+       if (unlikely(error)) {
+               dev_err(chip->dev, "SPI read error: %d\n", error);
+               return error;
+       }
+
+       for (i = 0; i < len; i++)
+               data[i] = be16_to_cpu(chip->xfer_buf[i + 1]);
 
-       return spi_write_then_read(spi, (u8 *)&tx, 2, (u8 *)data, 2);
+       return 0;
 }
 
-static int ad714x_spi_write(struct device *dev, unsigned short reg,
-               unsigned short data)
+static int ad714x_spi_write(struct ad714x_chip *chip,
+                           unsigned short reg, unsigned short data)
 {
-       struct spi_device *spi = to_spi_device(dev);
-       unsigned short tx[2] = {
-               AD714x_SPI_CMD_PREFIX | reg,
-               data
-       };
+       struct spi_device *spi = to_spi_device(chip->dev);
+       int error;
+
+       chip->xfer_buf[0] = cpu_to_be16(AD714x_SPI_CMD_PREFIX | reg);
+       chip->xfer_buf[1] = cpu_to_be16(data);
+
+       error = spi_write(spi, (u8 *)chip->xfer_buf,
+                         2 * sizeof(*chip->xfer_buf));
+       if (unlikely(error)) {
+               dev_err(chip->dev, "SPI write error: %d\n", error);
+               return error;
+       }
 
-       return spi_write(spi, (u8 *)tx, 4);
+       return 0;
 }
 
 static int __devinit ad714x_spi_probe(struct spi_device *spi)
 {
        struct ad714x_chip *chip;
+       int err;
+
+       spi->bits_per_word = 8;
+       err = spi_setup(spi);
+       if (err < 0)
+               return err;
 
        chip = ad714x_probe(&spi->dev, BUS_SPI, spi->irq,
                            ad714x_spi_read, ad714x_spi_write);
index c3a62c4..ca42c7d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * AD714X CapTouch Programmable Controller driver supporting AD7142/3/7/8/7A
  *
- * Copyright 2009 Analog Devices Inc.
+ * Copyright 2009-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -59,7 +59,6 @@
 #define STAGE11_AMBIENT                0x27D
 
 #define PER_STAGE_REG_NUM      36
-#define STAGE_NUM              12
 #define STAGE_CFGREG_NUM       8
 #define SYS_CFGREG_NUM         8
 
@@ -124,27 +123,6 @@ struct ad714x_driver_data {
  * information to integrate all things which will be private data
  * of spi/i2c device
  */
-struct ad714x_chip {
-       unsigned short h_state;
-       unsigned short l_state;
-       unsigned short c_state;
-       unsigned short adc_reg[STAGE_NUM];
-       unsigned short amb_reg[STAGE_NUM];
-       unsigned short sensor_val[STAGE_NUM];
-
-       struct ad714x_platform_data *hw;
-       struct ad714x_driver_data *sw;
-
-       int irq;
-       struct device *dev;
-       ad714x_read_t read;
-       ad714x_write_t write;
-
-       struct mutex mutex;
-
-       unsigned product;
-       unsigned version;
-};
 
 static void ad714x_use_com_int(struct ad714x_chip *ad714x,
                                int start_stage, int end_stage)
@@ -154,13 +132,13 @@ static void ad714x_use_com_int(struct ad714x_chip *ad714x,
 
        mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1);
 
-       ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data);
+       ad714x->read(ad714x, STG_COM_INT_EN_REG, &data, 1);
        data |= 1 << end_stage;
-       ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data);
+       ad714x->write(ad714x, STG_COM_INT_EN_REG, data);
 
-       ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data);
+       ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data, 1);
        data &= ~mask;
-       ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data);
+       ad714x->write(ad714x, STG_HIGH_INT_EN_REG, data);
 }
 
 static void ad714x_use_thr_int(struct ad714x_chip *ad714x,
@@ -171,13 +149,13 @@ static void ad714x_use_thr_int(struct ad714x_chip *ad714x,
 
        mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1);
 
-       ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data);
+       ad714x->read(ad714x, STG_COM_INT_EN_REG, &data, 1);
        data &= ~(1 << end_stage);
-       ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data);
+       ad714x->write(ad714x, STG_COM_INT_EN_REG, data);
 
-       ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data);
+       ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data, 1);
        data |= mask;
-       ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data);
+       ad714x->write(ad714x, STG_HIGH_INT_EN_REG, data);
 }
 
 static int ad714x_cal_highest_stage(struct ad714x_chip *ad714x,
@@ -273,15 +251,16 @@ static void ad714x_slider_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
        struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
        int i;
 
+       ad714x->read(ad714x, CDC_RESULT_S0 + hw->start_stage,
+                       &ad714x->adc_reg[hw->start_stage],
+                       hw->end_stage - hw->start_stage + 1);
+
        for (i = hw->start_stage; i <= hw->end_stage; i++) {
-               ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
-                       &ad714x->adc_reg[i]);
-               ad714x->read(ad714x->dev,
-                               STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
-                               &ad714x->amb_reg[i]);
-
-               ad714x->sensor_val[i] = abs(ad714x->adc_reg[i] -
-                               ad714x->amb_reg[i]);
+               ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
+                               &ad714x->amb_reg[i], 1);
+
+               ad714x->sensor_val[i] =
+                       abs(ad714x->adc_reg[i] - ad714x->amb_reg[i]);
        }
 }
 
@@ -444,15 +423,16 @@ static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
        struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
        int i;
 
+       ad714x->read(ad714x, CDC_RESULT_S0 + hw->start_stage,
+                       &ad714x->adc_reg[hw->start_stage],
+                       hw->end_stage - hw->start_stage + 1);
+
        for (i = hw->start_stage; i <= hw->end_stage; i++) {
-               ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
-                       &ad714x->adc_reg[i]);
-               ad714x->read(ad714x->dev,
-                               STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
-                               &ad714x->amb_reg[i]);
+               ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
+                               &ad714x->amb_reg[i], 1);
                if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
-                       ad714x->sensor_val[i] = ad714x->adc_reg[i] -
-                               ad714x->amb_reg[i];
+                       ad714x->sensor_val[i] =
+                               ad714x->adc_reg[i] - ad714x->amb_reg[i];
                else
                        ad714x->sensor_val[i] = 0;
        }
@@ -597,15 +577,16 @@ static void touchpad_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
        struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
        int i;
 
+       ad714x->read(ad714x, CDC_RESULT_S0 + hw->x_start_stage,
+                       &ad714x->adc_reg[hw->x_start_stage],
+                       hw->x_end_stage - hw->x_start_stage + 1);
+
        for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) {
-               ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
-                               &ad714x->adc_reg[i]);
-               ad714x->read(ad714x->dev,
-                               STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
-                               &ad714x->amb_reg[i]);
+               ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
+                               &ad714x->amb_reg[i], 1);
                if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
-                       ad714x->sensor_val[i] = ad714x->adc_reg[i] -
-                               ad714x->amb_reg[i];
+                       ad714x->sensor_val[i] =
+                               ad714x->adc_reg[i] - ad714x->amb_reg[i];
                else
                        ad714x->sensor_val[i] = 0;
        }
@@ -891,7 +872,7 @@ static int ad714x_hw_detect(struct ad714x_chip *ad714x)
 {
        unsigned short data;
 
-       ad714x->read(ad714x->dev, AD714X_PARTID_REG, &data);
+       ad714x->read(ad714x, AD714X_PARTID_REG, &data, 1);
        switch (data & 0xFFF0) {
        case AD7142_PARTID:
                ad714x->product = 0x7142;
@@ -940,23 +921,20 @@ static void ad714x_hw_init(struct ad714x_chip *ad714x)
        for (i = 0; i < STAGE_NUM; i++) {
                reg_base = AD714X_STAGECFG_REG + i * STAGE_CFGREG_NUM;
                for (j = 0; j < STAGE_CFGREG_NUM; j++)
-                       ad714x->write(ad714x->dev, reg_base + j,
+                       ad714x->write(ad714x, reg_base + j,
                                        ad714x->hw->stage_cfg_reg[i][j]);
        }
 
        for (i = 0; i < SYS_CFGREG_NUM; i++)
-               ad714x->write(ad714x->dev, AD714X_SYSCFG_REG + i,
+               ad714x->write(ad714x, AD714X_SYSCFG_REG + i,
                        ad714x->hw->sys_cfg_reg[i]);
        for (i = 0; i < SYS_CFGREG_NUM; i++)
-               ad714x->read(ad714x->dev, AD714X_SYSCFG_REG + i,
-                       &data);
+               ad714x->read(ad714x, AD714X_SYSCFG_REG + i, &data, 1);
 
-       ad714x->write(ad714x->dev, AD714X_STG_CAL_EN_REG, 0xFFF);
+       ad714x->write(ad714x, AD714X_STG_CAL_EN_REG, 0xFFF);
 
        /* clear all interrupts */
-       ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data);
-       ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data);
-       ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data);
+       ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
 }
 
 static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
@@ -966,9 +944,7 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
 
        mutex_lock(&ad714x->mutex);
 
-       ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &ad714x->l_state);
-       ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &ad714x->h_state);
-       ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &ad714x->c_state);
+       ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
 
        for (i = 0; i < ad714x->hw->button_num; i++)
                ad714x_button_state_machine(ad714x, i);
@@ -1245,7 +1221,7 @@ int ad714x_disable(struct ad714x_chip *ad714x)
        mutex_lock(&ad714x->mutex);
 
        data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3;
-       ad714x->write(ad714x->dev, AD714X_PWR_CTRL, data);
+       ad714x->write(ad714x, AD714X_PWR_CTRL, data);
 
        mutex_unlock(&ad714x->mutex);
 
@@ -1255,24 +1231,20 @@ EXPORT_SYMBOL(ad714x_disable);
 
 int ad714x_enable(struct ad714x_chip *ad714x)
 {
-       unsigned short data;
-
        dev_dbg(ad714x->dev, "%s enter\n", __func__);
 
        mutex_lock(&ad714x->mutex);
 
        /* resume to non-shutdown mode */
 
-       ad714x->write(ad714x->dev, AD714X_PWR_CTRL,
+       ad714x->write(ad714x, AD714X_PWR_CTRL,
                        ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL]);
 
        /* make sure the interrupt output line is not low level after resume,
         * otherwise we will get no chance to enter falling-edge irq again
         */
 
-       ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data);
-       ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data);
-       ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data);
+       ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
 
        mutex_unlock(&ad714x->mutex);
 
index 45c54fb..3c85455 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * AD714X CapTouch Programmable Controller driver (bus interfaces)
  *
- * Copyright 2009 Analog Devices Inc.
+ * Copyright 2009-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
 
 #include <linux/types.h>
 
+#define STAGE_NUM              12
+
 struct device;
+struct ad714x_platform_data;
+struct ad714x_driver_data;
 struct ad714x_chip;
 
-typedef int (*ad714x_read_t)(struct device *, unsigned short, unsigned short *);
-typedef int (*ad714x_write_t)(struct device *, unsigned short, unsigned short);
+typedef int (*ad714x_read_t)(struct ad714x_chip *, unsigned short, unsigned short *, size_t);
+typedef int (*ad714x_write_t)(struct ad714x_chip *, unsigned short, unsigned short);
+
+struct ad714x_chip {
+       unsigned short l_state;
+       unsigned short h_state;
+       unsigned short c_state;
+       unsigned short adc_reg[STAGE_NUM];
+       unsigned short amb_reg[STAGE_NUM];
+       unsigned short sensor_val[STAGE_NUM];
+
+       struct ad714x_platform_data *hw;
+       struct ad714x_driver_data *sw;
+
+       int irq;
+       struct device *dev;
+       ad714x_read_t read;
+       ad714x_write_t write;
+
+       struct mutex mutex;
+
+       unsigned product;
+       unsigned version;
+
+       __be16 xfer_buf[16] ____cacheline_aligned;
+
+};
 
 int ad714x_disable(struct ad714x_chip *ad714x);
 int ad714x_enable(struct ad714x_chip *ad714x);
index 6c76cf7..0794778 100644 (file)
@@ -234,7 +234,7 @@ static const struct of_device_id mma8450_dt_ids[] = {
        { .compatible = "fsl,mma8450", },
        { /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(i2c, mma8450_dt_ids);
+MODULE_DEVICE_TABLE(of, mma8450_dt_ids);
 
 static struct i2c_driver mma8450_driver = {
        .driver = {
index b95fac1..f71dc72 100644 (file)
@@ -282,7 +282,7 @@ err_free_irq:
 err_pm_set_suspended:
        pm_runtime_set_suspended(&client->dev);
 err_free_mem:
-       input_unregister_device(idev);
+       input_free_device(idev);
        kfree(sensor);
        return error;
 }
index 3126983..da28018 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI   0x0245
 #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO    0x0246
 #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS    0x0247
+/* MacbookAir4,2 (unibody, July 2011) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI   0x024c
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO    0x024d
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS    0x024e
+/* Macbook8,2 (unibody) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI  0x0252
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO   0x0253
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS   0x0254
 
 #define BCM5974_DEVICE(prod) {                                 \
        .match_flags = (USB_DEVICE_ID_MATCH_DEVICE |            \
@@ -104,6 +112,14 @@ static const struct usb_device_id bcm5974_table[] = {
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
+       /* MacbookAir4,2 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
+       /* MacbookPro8,2 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
        /* Terminating entry */
        {}
 };
@@ -294,6 +310,30 @@ static const struct bcm5974_config bcm5974_config_table[] = {
                { DIM_X, DIM_X / SN_COORD, -4415, 5050 },
                { DIM_Y, DIM_Y / SN_COORD, -55, 6680 }
        },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING6_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING6_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0x84, sizeof(struct bt_data),
+               0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+               { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+               { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+               { DIM_X, DIM_X / SN_COORD, -4620, 5140 },
+               { DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+       },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0x84, sizeof(struct bt_data),
+               0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+               { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+               { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+               { DIM_X, DIM_X / SN_COORD, -4750, 5280 },
+               { DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
+       },
        {}
 };
 
index 449c0a4..d27c9d9 100644 (file)
@@ -49,6 +49,7 @@ struct hid_descriptor {
 #define USB_REQ_GET_REPORT     0x01
 #define USB_REQ_SET_REPORT     0x09
 #define WAC_HID_FEATURE_REPORT 0x03
+#define WAC_MSG_RETRIES                5
 
 static int usb_get_report(struct usb_interface *intf, unsigned char type,
                                unsigned char id, void *buf, int size)
@@ -165,7 +166,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                        report,
                        hid_desc->wDescriptorLength,
                        5000); /* 5 secs */
-       } while (result < 0 && limit++ < 5);
+       } while (result < 0 && limit++ < WAC_MSG_RETRIES);
 
        /* No need to parse the Descriptor. It isn't an error though */
        if (result < 0)
@@ -319,24 +320,26 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
        int limit = 0, report_id = 2;
        int error = -ENOMEM;
 
-       rep_data = kmalloc(2, GFP_KERNEL);
+       rep_data = kmalloc(4, GFP_KERNEL);
        if (!rep_data)
                return error;
 
-       /* ask to report tablet data if it is 2FGT Tablet PC or
+       /* ask to report tablet data if it is MT Tablet PC or
         * not a Tablet PC */
        if (features->type == TABLETPC2FG) {
                do {
                        rep_data[0] = 3;
                        rep_data[1] = 4;
+                       rep_data[2] = 0;
+                       rep_data[3] = 0;
                        report_id = 3;
                        error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-                               report_id, rep_data, 2);
+                               report_id, rep_data, 4);
                        if (error >= 0)
                                error = usb_get_report(intf,
                                        WAC_HID_FEATURE_REPORT, report_id,
-                                       rep_data, 3);
-               } while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
+                                       rep_data, 4);
+               } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
        } else if (features->type != TABLETPC) {
                do {
                        rep_data[0] = 2;
@@ -347,7 +350,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
                                error = usb_get_report(intf,
                                        WAC_HID_FEATURE_REPORT, report_id,
                                        rep_data, 2);
-               } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+               } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES);
        }
 
        kfree(rep_data);
index 03ebcc8..c1c2f7b 100644 (file)
@@ -1460,6 +1460,9 @@ static const struct wacom_features wacom_features_0xD3 =
 static const struct wacom_features wacom_features_0xD4 =
        { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
          63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD5 =
+       { "Wacom Bamboo Pen 6x8",     WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
+         63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD6 =
        { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023,
          63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1564,6 +1567,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xD2) },
        { USB_DEVICE_WACOM(0xD3) },
        { USB_DEVICE_WACOM(0xD4) },
+       { USB_DEVICE_WACOM(0xD5) },
        { USB_DEVICE_WACOM(0xD6) },
        { USB_DEVICE_WACOM(0xD7) },
        { USB_DEVICE_WACOM(0xD8) },
index ae00604..f5d6685 100644 (file)
@@ -244,6 +244,7 @@ struct mxt_finger {
        int x;
        int y;
        int area;
+       int pressure;
 };
 
 /* Each client has this additional data */
@@ -536,6 +537,8 @@ static void mxt_input_report(struct mxt_data *data, int single_id)
                                        finger[id].x);
                        input_report_abs(input_dev, ABS_MT_POSITION_Y,
                                        finger[id].y);
+                       input_report_abs(input_dev, ABS_MT_PRESSURE,
+                                       finger[id].pressure);
                } else {
                        finger[id].status = 0;
                }
@@ -546,6 +549,8 @@ static void mxt_input_report(struct mxt_data *data, int single_id)
        if (status != MXT_RELEASE) {
                input_report_abs(input_dev, ABS_X, finger[single_id].x);
                input_report_abs(input_dev, ABS_Y, finger[single_id].y);
+               input_report_abs(input_dev,
+                                ABS_PRESSURE, finger[single_id].pressure);
        }
 
        input_sync(input_dev);
@@ -560,6 +565,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
        int x;
        int y;
        int area;
+       int pressure;
 
        /* Check the touch is present on the screen */
        if (!(status & MXT_DETECT)) {
@@ -584,6 +590,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
                y = y >> 2;
 
        area = message->message[4];
+       pressure = message->message[5];
 
        dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
                status & MXT_MOVE ? "moved" : "pressed",
@@ -594,6 +601,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
        finger[id].x = x;
        finger[id].y = y;
        finger[id].area = area;
+       finger[id].pressure = pressure;
 
        mxt_input_report(data, id);
 }
@@ -1116,6 +1124,8 @@ static int __devinit mxt_probe(struct i2c_client *client,
                             0, data->max_x, 0, 0);
        input_set_abs_params(input_dev, ABS_Y,
                             0, data->max_y, 0, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE,
+                            0, 255, 0, 0);
 
        /* For multi touch */
        input_mt_init_slots(input_dev, MXT_MAX_FINGER);
@@ -1125,6 +1135,8 @@ static int __devinit mxt_probe(struct i2c_client *client,
                             0, data->max_x, 0, 0);
        input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
                             0, data->max_y, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+                            0, 255, 0, 0);
 
        input_set_drvdata(input_dev, data);
        i2c_set_clientdata(client, data);
index 4f2713d..4627fe5 100644 (file)
@@ -9,7 +9,8 @@
  *
  * 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.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  */
 
 /*
index 089b0a0..0e8f63e 100644 (file)
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/errno.h>
index a14f8dc..0e4227f 100644 (file)
@@ -605,7 +605,9 @@ static void build_inv_all(struct iommu_cmd *cmd)
  * Writes the command to the IOMMUs command buffer and informs the
  * hardware about the new command.
  */
-static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
+static int iommu_queue_command_sync(struct amd_iommu *iommu,
+                                   struct iommu_cmd *cmd,
+                                   bool sync)
 {
        u32 left, tail, head, next_tail;
        unsigned long flags;
@@ -639,13 +641,18 @@ again:
        copy_cmd_to_buffer(iommu, cmd, tail);
 
        /* We need to sync now to make sure all commands are processed */
-       iommu->need_sync = true;
+       iommu->need_sync = sync;
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        return 0;
 }
 
+static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
+{
+       return iommu_queue_command_sync(iommu, cmd, true);
+}
+
 /*
  * This function queues a completion wait command into the command
  * buffer of an IOMMU
@@ -661,7 +668,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
 
        build_completion_wait(&cmd, (u64)&sem);
 
-       ret = iommu_queue_command(iommu, &cmd);
+       ret = iommu_queue_command_sync(iommu, &cmd, false);
        if (ret)
                return ret;
 
@@ -840,14 +847,9 @@ static void domain_flush_complete(struct protection_domain *domain)
 static void domain_flush_devices(struct protection_domain *domain)
 {
        struct iommu_dev_data *dev_data;
-       unsigned long flags;
-
-       spin_lock_irqsave(&domain->lock, flags);
 
        list_for_each_entry(dev_data, &domain->dev_list, list)
                device_flush_dte(dev_data);
-
-       spin_unlock_irqrestore(&domain->lock, flags);
 }
 
 /****************************************************************************
index b982603..8c00937 100644 (file)
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 3ebe382..ea21855 100644 (file)
@@ -662,6 +662,11 @@ failed_unregister_led1_R:
 static void bd2802_unregister_led_classdev(struct bd2802_led *led)
 {
        cancel_work_sync(&led->work);
+       led_classdev_unregister(&led->cdev_led2b);
+       led_classdev_unregister(&led->cdev_led2g);
+       led_classdev_unregister(&led->cdev_led2r);
+       led_classdev_unregister(&led->cdev_led1b);
+       led_classdev_unregister(&led->cdev_led1g);
        led_classdev_unregister(&led->cdev_led1r);
 }
 
index e4ce1fd..bcfbd3a 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 0ce29b6..2f2da05 100644 (file)
@@ -10,9 +10,9 @@ typedef struct dev_info dev_info_t;
 
 struct linear_private_data
 {
+       struct rcu_head         rcu;
        sector_t                array_sectors;
        dev_info_t              disks[0];
-       struct rcu_head         rcu;
 };
 
 
index 8e221a2..5404b22 100644 (file)
@@ -848,7 +848,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
        bio->bi_end_io = super_written;
 
        atomic_inc(&mddev->pending_writes);
-       submit_bio(REQ_WRITE | REQ_SYNC | REQ_FLUSH | REQ_FUA, bio);
+       submit_bio(WRITE_FLUSH_FUA, bio);
 }
 
 void md_super_wait(mddev_t *mddev)
@@ -1138,8 +1138,11 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
                        ret = 0;
        }
        rdev->sectors = rdev->sb_start;
+       /* Limit to 4TB as metadata cannot record more than that */
+       if (rdev->sectors >= (2ULL << 32))
+               rdev->sectors = (2ULL << 32) - 2;
 
-       if (rdev->sectors < sb->size * 2 && sb->level > 1)
+       if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1)
                /* "this cannot possibly happen" ... */
                ret = -EINVAL;
 
@@ -1173,7 +1176,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->clevel[0] = 0;
                mddev->layout = sb->layout;
                mddev->raid_disks = sb->raid_disks;
-               mddev->dev_sectors = sb->size * 2;
+               mddev->dev_sectors = ((sector_t)sb->size) * 2;
                mddev->events = ev1;
                mddev->bitmap_info.offset = 0;
                mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9;
@@ -1415,6 +1418,11 @@ super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
        rdev->sb_start = calc_dev_sboffset(rdev);
        if (!num_sectors || num_sectors > rdev->sb_start)
                num_sectors = rdev->sb_start;
+       /* Limit to 4TB as metadata cannot record more than that.
+        * 4TB == 2^32 KB, or 2*2^32 sectors.
+        */
+       if (num_sectors >= (2ULL << 32))
+               num_sectors = (2ULL << 32) - 2;
        md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
                       rdev->sb_page);
        md_super_wait(rdev->mddev);
@@ -1738,6 +1746,11 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
        sb->level = cpu_to_le32(mddev->level);
        sb->layout = cpu_to_le32(mddev->layout);
 
+       if (test_bit(WriteMostly, &rdev->flags))
+               sb->devflags |= WriteMostly1;
+       else
+               sb->devflags &= ~WriteMostly1;
+
        if (mddev->bitmap && mddev->bitmap_info.file == NULL) {
                sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_info.offset);
                sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
@@ -2561,7 +2574,10 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
        int err = -EINVAL;
        if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
                md_error(rdev->mddev, rdev);
-               err = 0;
+               if (test_bit(Faulty, &rdev->flags))
+                       err = 0;
+               else
+                       err = -EBUSY;
        } else if (cmd_match(buf, "remove")) {
                if (rdev->raid_disk >= 0)
                        err = -EBUSY;
@@ -2584,7 +2600,7 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
                err = 0;
        } else if (cmd_match(buf, "-blocked")) {
                if (!test_bit(Faulty, &rdev->flags) &&
-                   test_bit(BlockedBadBlocks, &rdev->flags)) {
+                   rdev->badblocks.unacked_exist) {
                        /* metadata handler doesn't understand badblocks,
                         * so we need to fail the device
                         */
@@ -5983,6 +5999,8 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
                return -ENODEV;
 
        md_error(mddev, rdev);
+       if (!test_bit(Faulty, &rdev->flags))
+               return -EBUSY;
        return 0;
 }
 
index 32323f0..f4622dd 100644 (file)
@@ -1099,12 +1099,11 @@ read_again:
                bio_list_add(&conf->pending_bio_list, mbio);
                spin_unlock_irqrestore(&conf->device_lock, flags);
        }
-       r1_bio_write_done(r1_bio);
-
-       /* In case raid1d snuck in to freeze_array */
-       wake_up(&conf->wait_barrier);
-
+       /* Mustn't call r1_bio_write_done before this next test,
+        * as it could result in the bio being freed.
+        */
        if (sectors_handled < (bio->bi_size >> 9)) {
+               r1_bio_write_done(r1_bio);
                /* We need another r1_bio.  It has already been counted
                 * in bio->bi_phys_segments
                 */
@@ -1117,6 +1116,11 @@ read_again:
                goto retry_write;
        }
 
+       r1_bio_write_done(r1_bio);
+
+       /* In case raid1d snuck in to freeze_array */
+       wake_up(&conf->wait_barrier);
+
        if (do_sync || !bitmap || !plugged)
                md_wakeup_thread(mddev->thread);
 
index 8b29cd4..d7a8468 100644 (file)
@@ -337,6 +337,21 @@ static void close_write(r10bio_t *r10_bio)
        md_write_end(r10_bio->mddev);
 }
 
+static void one_write_done(r10bio_t *r10_bio)
+{
+       if (atomic_dec_and_test(&r10_bio->remaining)) {
+               if (test_bit(R10BIO_WriteError, &r10_bio->state))
+                       reschedule_retry(r10_bio);
+               else {
+                       close_write(r10_bio);
+                       if (test_bit(R10BIO_MadeGood, &r10_bio->state))
+                               reschedule_retry(r10_bio);
+                       else
+                               raid_end_bio_io(r10_bio);
+               }
+       }
+}
+
 static void raid10_end_write_request(struct bio *bio, int error)
 {
        int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -387,17 +402,7 @@ static void raid10_end_write_request(struct bio *bio, int error)
         * Let's see if all mirrored write operations have finished
         * already.
         */
-       if (atomic_dec_and_test(&r10_bio->remaining)) {
-               if (test_bit(R10BIO_WriteError, &r10_bio->state))
-                       reschedule_retry(r10_bio);
-               else {
-                       close_write(r10_bio);
-                       if (test_bit(R10BIO_MadeGood, &r10_bio->state))
-                               reschedule_retry(r10_bio);
-                       else
-                               raid_end_bio_io(r10_bio);
-               }
-       }
+       one_write_done(r10_bio);
        if (dec_rdev)
                rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
 }
@@ -1127,20 +1132,12 @@ retry_write:
                spin_unlock_irqrestore(&conf->device_lock, flags);
        }
 
-       if (atomic_dec_and_test(&r10_bio->remaining)) {
-               /* This matches the end of raid10_end_write_request() */
-               bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
-                               r10_bio->sectors,
-                               !test_bit(R10BIO_Degraded, &r10_bio->state),
-                               0);
-               md_write_end(mddev);
-               raid_end_bio_io(r10_bio);
-       }
-
-       /* In case raid10d snuck in to freeze_array */
-       wake_up(&conf->wait_barrier);
+       /* Don't remove the bias on 'remaining' (one_write_done) until
+        * after checking if we need to go around again.
+        */
 
        if (sectors_handled < (bio->bi_size >> 9)) {
+               one_write_done(r10_bio);
                /* We need another r10_bio.  It has already been counted
                 * in bio->bi_phys_segments.
                 */
@@ -1154,6 +1151,10 @@ retry_write:
                r10_bio->state = 0;
                goto retry_write;
        }
+       one_write_done(r10_bio);
+
+       /* In case raid10d snuck in to freeze_array */
+       wake_up(&conf->wait_barrier);
 
        if (do_sync || !mddev->bitmap || !plugged)
                md_wakeup_thread(mddev->thread);
index dbae459..43709fa 100644 (file)
@@ -3336,7 +3336,7 @@ static void handle_stripe(struct stripe_head *sh)
 
 finish:
        /* wait for this device to become unblocked */
-       if (unlikely(s.blocked_rdev))
+       if (conf->mddev->external && unlikely(s.blocked_rdev))
                md_wait_for_blocked_rdev(s.blocked_rdev, conf->mddev);
 
        if (s.handle_bad_blocks)
index 3db89e3..536c16c 100644 (file)
@@ -224,26 +224,8 @@ static struct dvb_usb_device_properties vp7045_properties;
 static int vp7045_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       struct dvb_usb_device *d;
-       int ret = dvb_usb_device_init(intf, &vp7045_properties,
-                                  THIS_MODULE, &d, adapter_nr);
-       if (ret)
-               return ret;
-
-       d->priv = kmalloc(20, GFP_KERNEL);
-       if (!d->priv) {
-               dvb_usb_device_exit(intf);
-               return -ENOMEM;
-       }
-
-       return ret;
-}
-
-static void vp7045_usb_disconnect(struct usb_interface *intf)
-{
-       struct dvb_usb_device *d = usb_get_intfdata(intf);
-       kfree(d->priv);
-       dvb_usb_device_exit(intf);
+       return dvb_usb_device_init(intf, &vp7045_properties,
+                                  THIS_MODULE, NULL, adapter_nr);
 }
 
 static struct usb_device_id vp7045_usb_table [] = {
@@ -258,7 +240,7 @@ MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
 static struct dvb_usb_device_properties vp7045_properties = {
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-vp7045-01.fw",
-       .size_of_priv = sizeof(u8 *),
+       .size_of_priv = 20,
 
        .num_adapters = 1,
        .adapter = {
@@ -305,7 +287,7 @@ static struct dvb_usb_device_properties vp7045_properties = {
 static struct usb_driver vp7045_usb_driver = {
        .name           = "dvb_usb_vp7045",
        .probe          = vp7045_usb_probe,
-       .disconnect     = vp7045_usb_disconnect,
+       .disconnect     = dvb_usb_device_exit,
        .id_table       = vp7045_usb_table,
 };
 
index eae05b5..144f3f5 100644 (file)
@@ -618,7 +618,6 @@ static void nvt_dump_rx_buf(struct nvt_dev *nvt)
 static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 {
        DEFINE_IR_RAW_EVENT(rawir);
-       unsigned int count;
        u32 carrier;
        u8 sample;
        int i;
@@ -631,65 +630,38 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
        if (nvt->carrier_detect_enabled)
                carrier = nvt_rx_carrier_detect(nvt);
 
-       count = nvt->pkts;
-       nvt_dbg_verbose("Processing buffer of len %d", count);
+       nvt_dbg_verbose("Processing buffer of len %d", nvt->pkts);
 
        init_ir_raw_event(&rawir);
 
-       for (i = 0; i < count; i++) {
-               nvt->pkts--;
+       for (i = 0; i < nvt->pkts; i++) {
                sample = nvt->buf[i];
 
                rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
                rawir.duration = US_TO_NS((sample & BUF_LEN_MASK)
                                          * SAMPLE_PERIOD);
 
-               if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) {
-                       if (nvt->rawir.pulse == rawir.pulse)
-                               nvt->rawir.duration += rawir.duration;
-                       else {
-                               nvt->rawir.duration = rawir.duration;
-                               nvt->rawir.pulse = rawir.pulse;
-                       }
-                       continue;
-               }
-
-               rawir.duration += nvt->rawir.duration;
+               nvt_dbg("Storing %s with duration %d",
+                       rawir.pulse ? "pulse" : "space", rawir.duration);
 
-               init_ir_raw_event(&nvt->rawir);
-               nvt->rawir.duration = 0;
-               nvt->rawir.pulse = rawir.pulse;
-
-               if (sample == BUF_PULSE_BIT)
-                       rawir.pulse = false;
-
-               if (rawir.duration) {
-                       nvt_dbg("Storing %s with duration %d",
-                               rawir.pulse ? "pulse" : "space",
-                               rawir.duration);
-
-                       ir_raw_event_store_with_filter(nvt->rdev, &rawir);
-               }
+               ir_raw_event_store_with_filter(nvt->rdev, &rawir);
 
                /*
                 * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE
                 * indicates end of IR signal, but new data incoming. In both
                 * cases, it means we're ready to call ir_raw_event_handle
                 */
-               if ((sample == BUF_PULSE_BIT) && nvt->pkts) {
+               if ((sample == BUF_PULSE_BIT) && (i + 1 < nvt->pkts)) {
                        nvt_dbg("Calling ir_raw_event_handle (signal end)\n");
                        ir_raw_event_handle(nvt->rdev);
                }
        }
 
+       nvt->pkts = 0;
+
        nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n");
        ir_raw_event_handle(nvt->rdev);
 
-       if (nvt->pkts) {
-               nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);
-               nvt->pkts = 0;
-       }
-
        nvt_dbg_verbose("%s done", __func__);
 }
 
@@ -1048,7 +1020,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 
        spin_lock_init(&nvt->nvt_lock);
        spin_lock_init(&nvt->tx.lock);
-       init_ir_raw_event(&nvt->rawir);
 
        ret = -EBUSY;
        /* now claim resources */
index 1241fc8..0d5e087 100644 (file)
@@ -67,7 +67,6 @@ static int debug;
 struct nvt_dev {
        struct pnp_dev *pdev;
        struct rc_dev *rdev;
-       struct ir_raw_event rawir;
 
        spinlock_t nvt_lock;
 
index 0800433..18305c8 100644 (file)
@@ -2858,7 +2858,6 @@ static void ov7xx0_configure(struct sd *sd)
                        case 0x60:
                                PDEBUG(D_PROBE, "Sensor is a OV7660");
                                sd->sensor = SEN_OV7660;
-                               sd->invert_led = 0;
                                break;
                        default:
                                PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
@@ -3337,7 +3336,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        case BRIDGE_OV519:
                cam->cam_mode = ov519_vga_mode;
                cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-               sd->invert_led = !sd->invert_led;
                break;
        case BRIDGE_OVFX2:
                cam->cam_mode = ov519_vga_mode;
@@ -5005,24 +5003,24 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
-       {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x405f),
+       {USB_DEVICE(0x041e, 0x4052),
                .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+       {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x4064),
-               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+       {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x4068),
+       {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x045e, 0x028c),
                .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
-       {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x054c, 0x0155),
-               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+       {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
        {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
-       {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x05a9, 0x0519),
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+       {USB_DEVICE(0x05a9, 0x0530),
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
        {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
        {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
index 81b8a60..c477ad1 100644 (file)
@@ -2386,7 +2386,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
                reg_w1(gspca_dev, 0x01, 0x22);
                msleep(100);
                reg01 = SCL_SEL_OD | S_PDN_INV;
-               reg17 &= MCK_SIZE_MASK;
+               reg17 &= ~MCK_SIZE_MASK;
                reg17 |= 0x04;          /* clock / 4 */
                break;
        }
@@ -2532,6 +2532,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
                if (!mode) {                    /* if 640x480 */
                        reg17 &= ~MCK_SIZE_MASK;
                        reg17 |= 0x04;          /* clock / 4 */
+               } else {
+                       reg01 &= ~SYS_SEL_48M;  /* clk 24Mz */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x02;          /* clock / 2 */
                }
                break;
        case SENSOR_OV7630:
index e9a0e94..8c70e64 100644 (file)
@@ -338,7 +338,7 @@ int pwc_init_controls(struct pwc_device *pdev)
        if (pdev->restore_factory)
                pdev->restore_factory->flags = V4L2_CTRL_FLAG_UPDATE;
 
-       if (!pdev->features & FEATURE_MOTOR_PANTILT)
+       if (!(pdev->features & FEATURE_MOTOR_PANTILT))
                return hdl->error;
 
        /* Motor pan / tilt / reset */
index 85d3048..bb7f17f 100644 (file)
@@ -1332,6 +1332,8 @@ static __devinit bool viacam_serial_is_enabled(void)
        struct pci_bus *pbus = pci_find_bus(0, 0);
        u8 cbyte;
 
+       if (!pbus)
+               return false;
        pci_bus_read_config_byte(pbus, VIACAM_SERIAL_DEVFN,
                        VIACAM_SERIAL_CREG, &cbyte);
        if ((cbyte & VIACAM_SERIAL_BIT) == 0)
index 0a4d86c..2d6423c 100644 (file)
@@ -146,6 +146,7 @@ config PHANTOM
 
 config INTEL_MID_PTI
        tristate "Parallel Trace Interface for MIPI P1149.7 cJTAG standard"
+       depends on PCI
        default n
        help
          The PTI (Parallel Trace Interface) driver directs
index 54e3d05..3590315 100644 (file)
@@ -164,5 +164,5 @@ subsys_initcall(ab8500_pwm_init);
 module_exit(ab8500_pwm_exit);
 MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>");
 MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver");
-MODULE_ALIAS("AB8500 PWM driver");
+MODULE_ALIAS("platform:ab8500-pwm");
 MODULE_LICENSE("GPL v2");
index efec413..68cd05b 100644 (file)
@@ -33,7 +33,7 @@ EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg);
 static int __devinit cb710_pci_configure(struct pci_dev *pdev)
 {
        unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
-       struct pci_dev *pdev0 = pci_get_slot(pdev->bus, devfn);
+       struct pci_dev *pdev0;
        u32 val;
 
        cb710_pci_update_config_reg(pdev, 0x48,
@@ -43,6 +43,7 @@ static int __devinit cb710_pci_configure(struct pci_dev *pdev)
        if (val & 0x80000000)
                return 0;
 
+       pdev0 = pci_get_slot(pdev->bus, devfn);
        if (!pdev0)
                return -ENODEV;
 
index 5325a7e..27dc0d2 100644 (file)
@@ -455,7 +455,7 @@ static int __devinit fsa9480_probe(struct i2c_client *client,
 
 fail2:
        if (client->irq)
-               free_irq(client->irq, NULL);
+               free_irq(client->irq, usbsw);
 fail1:
        i2c_set_clientdata(client, NULL);
        kfree(usbsw);
@@ -466,7 +466,7 @@ static int __devexit fsa9480_remove(struct i2c_client *client)
 {
        struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
        if (client->irq)
-               free_irq(client->irq, NULL);
+               free_irq(client->irq, usbsw);
        i2c_set_clientdata(client, NULL);
 
        sysfs_remove_group(&client->dev.kobj, &fsa9480_group);
index 8653bd0..06df187 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/mutex.h>
 #include <linux/miscdevice.h>
 #include <linux/pti.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
 
 #define DRIVERNAME             "pti"
 #define PCINAME                        "pciPTI"
index 54c91ff..ba168a7 100644 (file)
@@ -338,6 +338,12 @@ void st_int_recv(void *disc_data,
                        /* Unknow packet? */
                default:
                        type = *ptr;
+                       if (st_gdata->list[type] == NULL) {
+                               pr_err("chip/interface misbehavior dropping"
+                                       " frame starting with 0x%02x", type);
+                               goto done;
+
+                       }
                        st_gdata->rx_skb = alloc_skb(
                                        st_gdata->list[type]->max_frame_size,
                                        GFP_ATOMIC);
@@ -354,6 +360,7 @@ void st_int_recv(void *disc_data,
                ptr++;
                count--;
        }
+done:
        spin_unlock_irqrestore(&st_gdata->lock, flags);
        pr_debug("done %s", __func__);
        return;
@@ -717,9 +724,10 @@ static void st_tty_close(struct tty_struct *tty)
         */
        spin_lock_irqsave(&st_gdata->lock, flags);
        for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
-               if (st_gdata->list[i] != NULL)
+               if (st_gdata->is_registered[i] == true)
                        pr_err("%d not un-registered", i);
                st_gdata->list[i] = NULL;
+               st_gdata->is_registered[i] = false;
        }
        st_gdata->protos_registered = 0;
        spin_unlock_irqrestore(&st_gdata->lock, flags);
index 38fd2f0..3a35805 100644 (file)
@@ -68,6 +68,7 @@ void validate_firmware_response(struct kim_data_s *kim_gdata)
        if (unlikely(skb->data[5] != 0)) {
                pr_err("no proper response during fw download");
                pr_err("data6 %x", skb->data[5]);
+               kfree_skb(skb);
                return;         /* keep waiting for the proper response */
        }
        /* becos of all the script being downloaded */
@@ -210,6 +211,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
                pr_err(" waiting for ver info- timed out ");
                return -ETIMEDOUT;
        }
+       INIT_COMPLETION(kim_gdata->kim_rcvd);
 
        version =
                MAKEWORD(kim_gdata->resp_buffer[13],
@@ -298,6 +300,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
 
                switch (((struct bts_action *)ptr)->type) {
                case ACTION_SEND_COMMAND:       /* action send */
+                       pr_debug("S");
                        action_ptr = &(((struct bts_action *)ptr)->data[0]);
                        if (unlikely
                            (((struct hci_command *)action_ptr)->opcode ==
@@ -335,6 +338,10 @@ static long download_firmware(struct kim_data_s *kim_gdata)
                                release_firmware(kim_gdata->fw_entry);
                                return -ETIMEDOUT;
                        }
+                       /* reinit completion before sending for the
+                        * relevant wait
+                        */
+                       INIT_COMPLETION(kim_gdata->kim_rcvd);
 
                        /*
                         * Free space found in uart buffer, call st_int_write
@@ -361,6 +368,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
                        }
                        break;
                case ACTION_WAIT_EVENT:  /* wait */
+                       pr_debug("W");
                        if (!wait_for_completion_timeout
                                        (&kim_gdata->kim_rcvd,
                                         msecs_to_jiffies(CMD_RESP_TIME))) {
@@ -434,11 +442,17 @@ long st_kim_start(void *kim_data)
 {
        long err = 0;
        long retry = POR_RETRY_COUNT;
+       struct ti_st_plat_data  *pdata;
        struct kim_data_s       *kim_gdata = (struct kim_data_s *)kim_data;
 
        pr_info(" %s", __func__);
+       pdata = kim_gdata->kim_pdev->dev.platform_data;
 
        do {
+               /* platform specific enabling code here */
+               if (pdata->chip_enable)
+                       pdata->chip_enable(kim_gdata);
+
                /* Configure BT nShutdown to HIGH state */
                gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
                mdelay(5);      /* FIXME: a proper toggle */
@@ -460,6 +474,12 @@ long st_kim_start(void *kim_data)
                        pr_info("ldisc_install = 0");
                        sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
                                        NULL, "install");
+                       /* the following wait is never going to be completed,
+                        * since the ldisc was never installed, hence serving
+                        * as a mdelay of LDISC_TIME msecs */
+                       err = wait_for_completion_timeout
+                               (&kim_gdata->ldisc_installed,
+                                msecs_to_jiffies(LDISC_TIME));
                        err = -ETIMEDOUT;
                        continue;
                } else {
@@ -472,6 +492,13 @@ long st_kim_start(void *kim_data)
                                pr_info("ldisc_install = 0");
                                sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
                                                NULL, "install");
+                               /* this wait might be completed, though in the
+                                * tty_close() since the ldisc is already
+                                * installed */
+                               err = wait_for_completion_timeout
+                                       (&kim_gdata->ldisc_installed,
+                                        msecs_to_jiffies(LDISC_TIME));
+                               err = -EINVAL;
                                continue;
                        } else {        /* on success don't retry */
                                break;
@@ -489,6 +516,8 @@ long st_kim_stop(void *kim_data)
 {
        long err = 0;
        struct kim_data_s       *kim_gdata = (struct kim_data_s *)kim_data;
+       struct ti_st_plat_data  *pdata =
+               kim_gdata->kim_pdev->dev.platform_data;
 
        INIT_COMPLETION(kim_gdata->ldisc_installed);
 
@@ -515,6 +544,10 @@ long st_kim_stop(void *kim_data)
        gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
        mdelay(1);
        gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+
+       /* platform specific disable */
+       if (pdata->chip_disable)
+               pdata->chip_disable(kim_gdata);
        return err;
 }
 
index 3f24951..1ff460a 100644 (file)
@@ -22,6 +22,7 @@
 #define pr_fmt(fmt) "(stll) :" fmt
 #include <linux/skbuff.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/ti_wilink_st.h>
 
 /**********************************************************************/
@@ -37,6 +38,9 @@ static void send_ll_cmd(struct st_data_s *st_data,
 
 static void ll_device_want_to_sleep(struct st_data_s *st_data)
 {
+       struct kim_data_s       *kim_data;
+       struct ti_st_plat_data  *pdata;
+
        pr_debug("%s", __func__);
        /* sanity check */
        if (st_data->ll_state != ST_LL_AWAKE)
@@ -46,10 +50,19 @@ static void ll_device_want_to_sleep(struct st_data_s *st_data)
        send_ll_cmd(st_data, LL_SLEEP_ACK);
        /* update state */
        st_data->ll_state = ST_LL_ASLEEP;
+
+       /* communicate to platform about chip asleep */
+       kim_data = st_data->kim_data;
+       pdata = kim_data->kim_pdev->dev.platform_data;
+       if (pdata->chip_asleep)
+               pdata->chip_asleep(NULL);
 }
 
 static void ll_device_want_to_wakeup(struct st_data_s *st_data)
 {
+       struct kim_data_s       *kim_data;
+       struct ti_st_plat_data  *pdata;
+
        /* diff actions in diff states */
        switch (st_data->ll_state) {
        case ST_LL_ASLEEP:
@@ -70,6 +83,12 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data)
        }
        /* update state */
        st_data->ll_state = ST_LL_AWAKE;
+
+       /* communicate to platform about chip wakeup */
+       kim_data = st_data->kim_data;
+       pdata = kim_data->kim_pdev->dev.platform_data;
+       if (pdata->chip_asleep)
+               pdata->chip_awake(NULL);
 }
 
 /**********************************************************************/
index 006a5e9..2bf229a 100644 (file)
@@ -224,7 +224,7 @@ static void mmc_test_prepare_mrq(struct mmc_test_card *test,
 static int mmc_test_busy(struct mmc_command *cmd)
 {
        return !(cmd->resp[0] & R1_READY_FOR_DATA) ||
-               (R1_CURRENT_STATE(cmd->resp[0]) == 7);
+               (R1_CURRENT_STATE(cmd->resp[0]) == R1_STATE_PRG);
 }
 
 /*
@@ -2900,7 +2900,7 @@ static const struct file_operations mmc_test_fops_testlist = {
        .release        = single_release,
 };
 
-static void mmc_test_free_file_test(struct mmc_card *card)
+static void mmc_test_free_dbgfs_file(struct mmc_card *card)
 {
        struct mmc_test_dbgfs_file *df, *dfs;
 
@@ -2917,34 +2917,21 @@ static void mmc_test_free_file_test(struct mmc_card *card)
        mutex_unlock(&mmc_test_lock);
 }
 
-static int mmc_test_register_file_test(struct mmc_card *card)
+static int __mmc_test_register_dbgfs_file(struct mmc_card *card,
+       const char *name, mode_t mode, const struct file_operations *fops)
 {
        struct dentry *file = NULL;
        struct mmc_test_dbgfs_file *df;
-       int ret = 0;
-
-       mutex_lock(&mmc_test_lock);
-
-       if (card->debugfs_root)
-               file = debugfs_create_file("test", S_IWUSR | S_IRUGO,
-                       card->debugfs_root, card, &mmc_test_fops_test);
-
-       if (IS_ERR_OR_NULL(file)) {
-               dev_err(&card->dev,
-                       "Can't create test. Perhaps debugfs is disabled.\n");
-               ret = -ENODEV;
-               goto err;
-       }
 
        if (card->debugfs_root)
-               file = debugfs_create_file("testlist", S_IRUGO,
-                       card->debugfs_root, card, &mmc_test_fops_testlist);
+               file = debugfs_create_file(name, mode, card->debugfs_root,
+                       card, fops);
 
        if (IS_ERR_OR_NULL(file)) {
                dev_err(&card->dev,
-                       "Can't create testlist. Perhaps debugfs is disabled.\n");
-               ret = -ENODEV;
-               goto err;
+                       "Can't create %s. Perhaps debugfs is disabled.\n",
+                       name);
+               return -ENODEV;
        }
 
        df = kmalloc(sizeof(struct mmc_test_dbgfs_file), GFP_KERNEL);
@@ -2952,14 +2939,31 @@ static int mmc_test_register_file_test(struct mmc_card *card)
                debugfs_remove(file);
                dev_err(&card->dev,
                        "Can't allocate memory for internal usage.\n");
-               ret = -ENOMEM;
-               goto err;
+               return -ENOMEM;
        }
 
        df->card = card;
        df->file = file;
 
        list_add(&df->link, &mmc_test_file_test);
+       return 0;
+}
+
+static int mmc_test_register_dbgfs_file(struct mmc_card *card)
+{
+       int ret;
+
+       mutex_lock(&mmc_test_lock);
+
+       ret = __mmc_test_register_dbgfs_file(card, "test", S_IWUSR | S_IRUGO,
+               &mmc_test_fops_test);
+       if (ret)
+               goto err;
+
+       ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO,
+               &mmc_test_fops_testlist);
+       if (ret)
+               goto err;
 
 err:
        mutex_unlock(&mmc_test_lock);
@@ -2974,7 +2978,7 @@ static int mmc_test_probe(struct mmc_card *card)
        if (!mmc_card_mmc(card) && !mmc_card_sd(card))
                return -ENODEV;
 
-       ret = mmc_test_register_file_test(card);
+       ret = mmc_test_register_dbgfs_file(card);
        if (ret)
                return ret;
 
@@ -2986,7 +2990,7 @@ static int mmc_test_probe(struct mmc_card *card)
 static void mmc_test_remove(struct mmc_card *card)
 {
        mmc_test_free_result(card);
-       mmc_test_free_file_test(card);
+       mmc_test_free_dbgfs_file(card);
 }
 
 static struct mmc_driver mmc_driver = {
@@ -3006,7 +3010,7 @@ static void __exit mmc_test_exit(void)
 {
        /* Clear stalled data if card is still plugged */
        mmc_test_free_result(NULL);
-       mmc_test_free_file_test(NULL);
+       mmc_test_free_dbgfs_file(NULL);
 
        mmc_unregister_driver(&mmc_driver);
 }
index 89bdeae..b27b940 100644 (file)
@@ -133,7 +133,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
                if (mrq->done)
                        mrq->done(mrq);
 
-               mmc_host_clk_gate(host);
+               mmc_host_clk_release(host);
        }
 }
 
@@ -192,7 +192,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
                        mrq->stop->mrq = mrq;
                }
        }
-       mmc_host_clk_ungate(host);
+       mmc_host_clk_hold(host);
        led_trigger_event(host->led, LED_FULL);
        host->ops->request(host, mrq);
 }
@@ -728,15 +728,17 @@ static inline void mmc_set_ios(struct mmc_host *host)
  */
 void mmc_set_chip_select(struct mmc_host *host, int mode)
 {
+       mmc_host_clk_hold(host);
        host->ios.chip_select = mode;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /*
  * Sets the host clock to the highest possible frequency that
  * is below "hz".
  */
-void mmc_set_clock(struct mmc_host *host, unsigned int hz)
+static void __mmc_set_clock(struct mmc_host *host, unsigned int hz)
 {
        WARN_ON(hz < host->f_min);
 
@@ -747,6 +749,13 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz)
        mmc_set_ios(host);
 }
 
+void mmc_set_clock(struct mmc_host *host, unsigned int hz)
+{
+       mmc_host_clk_hold(host);
+       __mmc_set_clock(host, hz);
+       mmc_host_clk_release(host);
+}
+
 #ifdef CONFIG_MMC_CLKGATE
 /*
  * This gates the clock by setting it to 0 Hz.
@@ -779,7 +788,7 @@ void mmc_ungate_clock(struct mmc_host *host)
        if (host->clk_old) {
                BUG_ON(host->ios.clock);
                /* This call will also set host->clk_gated to false */
-               mmc_set_clock(host, host->clk_old);
+               __mmc_set_clock(host, host->clk_old);
        }
 }
 
@@ -807,8 +816,10 @@ void mmc_set_ungated(struct mmc_host *host)
  */
 void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
 {
+       mmc_host_clk_hold(host);
        host->ios.bus_mode = mode;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /*
@@ -816,8 +827,10 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
  */
 void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
 {
+       mmc_host_clk_hold(host);
        host->ios.bus_width = width;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /**
@@ -1015,8 +1028,10 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
 
                ocr &= 3 << bit;
 
+               mmc_host_clk_hold(host);
                host->ios.vdd = bit;
                mmc_set_ios(host);
+               mmc_host_clk_release(host);
        } else {
                pr_warning("%s: host doesn't support card's voltages\n",
                                mmc_hostname(host));
@@ -1063,8 +1078,10 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11
  */
 void mmc_set_timing(struct mmc_host *host, unsigned int timing)
 {
+       mmc_host_clk_hold(host);
        host->ios.timing = timing;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /*
@@ -1072,8 +1089,10 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing)
  */
 void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
 {
+       mmc_host_clk_hold(host);
        host->ios.drv_type = drv_type;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /*
@@ -1091,6 +1110,8 @@ static void mmc_power_up(struct mmc_host *host)
 {
        int bit;
 
+       mmc_host_clk_hold(host);
+
        /* If ocr is set, we use it */
        if (host->ocr)
                bit = ffs(host->ocr) - 1;
@@ -1126,10 +1147,14 @@ static void mmc_power_up(struct mmc_host *host)
         * time required to reach a stable voltage.
         */
        mmc_delay(10);
+
+       mmc_host_clk_release(host);
 }
 
 static void mmc_power_off(struct mmc_host *host)
 {
+       mmc_host_clk_hold(host);
+
        host->ios.clock = 0;
        host->ios.vdd = 0;
 
@@ -1147,6 +1172,8 @@ static void mmc_power_off(struct mmc_host *host)
        host->ios.bus_width = MMC_BUS_WIDTH_1;
        host->ios.timing = MMC_TIMING_LEGACY;
        mmc_set_ios(host);
+
+       mmc_host_clk_release(host);
 }
 
 /*
@@ -1502,7 +1529,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
                        goto out;
                }
        } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
-                R1_CURRENT_STATE(cmd.resp[0]) == 7);
+                R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG);
 out:
        return err;
 }
index b29d3e8..793d0a0 100644 (file)
@@ -119,14 +119,14 @@ static void mmc_host_clk_gate_work(struct work_struct *work)
 }
 
 /**
- *     mmc_host_clk_ungate - ungate hardware MCI clocks
+ *     mmc_host_clk_hold - ungate hardware MCI clocks
  *     @host: host to ungate.
  *
  *     Makes sure the host ios.clock is restored to a non-zero value
  *     past this call. Increase clock reference count and ungate clock
  *     if we're the first user.
  */
-void mmc_host_clk_ungate(struct mmc_host *host)
+void mmc_host_clk_hold(struct mmc_host *host)
 {
        unsigned long flags;
 
@@ -164,14 +164,14 @@ static bool mmc_host_may_gate_card(struct mmc_card *card)
 }
 
 /**
- *     mmc_host_clk_gate - gate off hardware MCI clocks
+ *     mmc_host_clk_release - gate off hardware MCI clocks
  *     @host: host to gate.
  *
  *     Calls the host driver with ios.clock set to zero as often as possible
  *     in order to gate off hardware MCI clocks. Decrease clock reference
  *     count and schedule disabling of clock.
  */
-void mmc_host_clk_gate(struct mmc_host *host)
+void mmc_host_clk_release(struct mmc_host *host)
 {
        unsigned long flags;
 
@@ -179,7 +179,7 @@ void mmc_host_clk_gate(struct mmc_host *host)
        host->clk_requests--;
        if (mmc_host_may_gate_card(host->card) &&
            !host->clk_requests)
-               schedule_work(&host->clk_gate_work);
+               queue_work(system_nrt_wq, &host->clk_gate_work);
        spin_unlock_irqrestore(&host->clk_lock, flags);
 }
 
@@ -231,7 +231,7 @@ static inline void mmc_host_clk_exit(struct mmc_host *host)
        if (cancel_work_sync(&host->clk_gate_work))
                mmc_host_clk_gate_delayed(host);
        if (host->clk_gated)
-               mmc_host_clk_ungate(host);
+               mmc_host_clk_hold(host);
        /* There should be only one user now */
        WARN_ON(host->clk_requests > 1);
 }
index de199f9..fb8a5cd 100644 (file)
@@ -16,16 +16,16 @@ int mmc_register_host_class(void);
 void mmc_unregister_host_class(void);
 
 #ifdef CONFIG_MMC_CLKGATE
-void mmc_host_clk_ungate(struct mmc_host *host);
-void mmc_host_clk_gate(struct mmc_host *host);
+void mmc_host_clk_hold(struct mmc_host *host);
+void mmc_host_clk_release(struct mmc_host *host);
 unsigned int mmc_host_clk_rate(struct mmc_host *host);
 
 #else
-static inline void mmc_host_clk_ungate(struct mmc_host *host)
+static inline void mmc_host_clk_hold(struct mmc_host *host)
 {
 }
 
-static inline void mmc_host_clk_gate(struct mmc_host *host)
+static inline void mmc_host_clk_release(struct mmc_host *host)
 {
 }
 
index aa7d1d7..5700b1c 100644 (file)
@@ -259,7 +259,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
        }
 
        card->ext_csd.rev = ext_csd[EXT_CSD_REV];
-       if (card->ext_csd.rev > 5) {
+       if (card->ext_csd.rev > 6) {
                printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n",
                        mmc_hostname(card->host), card->ext_csd.rev);
                err = -EINVAL;
index 845ce7c..770c3d0 100644 (file)
@@ -407,7 +407,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
                        break;
                if (mmc_host_is_spi(card->host))
                        break;
-       } while (R1_CURRENT_STATE(status) == 7);
+       } while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
 
        if (mmc_host_is_spi(card->host)) {
                if (status & R1_SPI_ILLEGAL_COMMAND)
index 633975f..0370e03 100644 (file)
@@ -469,56 +469,75 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
        return 0;
 }
 
-static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
+static void sd_update_bus_speed_mode(struct mmc_card *card)
 {
-       unsigned int bus_speed = 0, timing = 0;
-       int err;
-
        /*
         * If the host doesn't support any of the UHS-I modes, fallback on
         * default speed.
         */
        if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
-           MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50)))
-               return 0;
+           MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))) {
+               card->sd_bus_speed = 0;
+               return;
+       }
 
        if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
            (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
-                       bus_speed = UHS_SDR104_BUS_SPEED;
-                       timing = MMC_TIMING_UHS_SDR104;
-                       card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR;
+                       card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
        } else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
                   (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
-                       bus_speed = UHS_DDR50_BUS_SPEED;
-                       timing = MMC_TIMING_UHS_DDR50;
-                       card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR;
+                       card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
        } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
                    MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
                    SD_MODE_UHS_SDR50)) {
-                       bus_speed = UHS_SDR50_BUS_SPEED;
-                       timing = MMC_TIMING_UHS_SDR50;
-                       card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR;
+                       card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
        } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
                    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
                   (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
-                       bus_speed = UHS_SDR25_BUS_SPEED;
-                       timing = MMC_TIMING_UHS_SDR25;
-                       card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR;
+                       card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
        } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
                    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
                    MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
                    SD_MODE_UHS_SDR12)) {
-                       bus_speed = UHS_SDR12_BUS_SPEED;
-                       timing = MMC_TIMING_UHS_SDR12;
-                       card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR;
+                       card->sd_bus_speed = UHS_SDR12_BUS_SPEED;
+       }
+}
+
+static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
+{
+       int err;
+       unsigned int timing = 0;
+
+       switch (card->sd_bus_speed) {
+       case UHS_SDR104_BUS_SPEED:
+               timing = MMC_TIMING_UHS_SDR104;
+               card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR;
+               break;
+       case UHS_DDR50_BUS_SPEED:
+               timing = MMC_TIMING_UHS_DDR50;
+               card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR;
+               break;
+       case UHS_SDR50_BUS_SPEED:
+               timing = MMC_TIMING_UHS_SDR50;
+               card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR;
+               break;
+       case UHS_SDR25_BUS_SPEED:
+               timing = MMC_TIMING_UHS_SDR25;
+               card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR;
+               break;
+       case UHS_SDR12_BUS_SPEED:
+               timing = MMC_TIMING_UHS_SDR12;
+               card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR;
+               break;
+       default:
+               return 0;
        }
 
-       card->sd_bus_speed = bus_speed;
-       err = mmc_sd_switch(card, 1, 0, bus_speed, status);
+       err = mmc_sd_switch(card, 1, 0, card->sd_bus_speed, status);
        if (err)
                return err;
 
-       if ((status[16] & 0xF) != bus_speed)
+       if ((status[16] & 0xF) != card->sd_bus_speed)
                printk(KERN_WARNING "%s: Problem setting bus speed mode!\n",
                        mmc_hostname(card->host));
        else {
@@ -618,18 +637,24 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
                mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
        }
 
+       /*
+        * Select the bus speed mode depending on host
+        * and card capability.
+        */
+       sd_update_bus_speed_mode(card);
+
        /* Set the driver strength for the card */
        err = sd_select_driver_type(card, status);
        if (err)
                goto out;
 
-       /* Set bus speed mode of the card */
-       err = sd_set_bus_speed_mode(card, status);
+       /* Set current limit for the card */
+       err = sd_set_current_limit(card, status);
        if (err)
                goto out;
 
-       /* Set current limit for the card */
-       err = sd_set_current_limit(card, status);
+       /* Set bus speed mode of the card */
+       err = sd_set_bus_speed_mode(card, status);
        if (err)
                goto out;
 
index 77f0b6b..ff0f714 100644 (file)
@@ -62,7 +62,7 @@ struct idmac_desc {
 
        u32             des1;   /* Buffer sizes */
 #define IDMAC_SET_BUFFER1_SIZE(d, s) \
-       ((d)->des1 = ((d)->des1 & 0x03ffc000) | ((s) & 0x3fff))
+       ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff))
 
        u32             des2;   /* buffer 1 physical address */
 
@@ -699,7 +699,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        }
 
        /* DDR mode set */
-       if (ios->ddr) {
+       if (ios->timing == MMC_TIMING_UHS_DDR50) {
                regs = mci_readl(slot->host, UHS_REG);
                regs |= (0x1 << slot->id) << 16;
                mci_writel(slot->host, UHS_REG, regs);
@@ -1646,7 +1646,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                        mmc->caps |= MMC_CAP_4_BIT_DATA;
 
        if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED)
-               mmc->caps |= MMC_CAP_SD_HIGHSPEED;
+               mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
 #ifdef CONFIG_MMC_DW_IDMAC
        mmc->max_segs = host->ring_size;
index 9ebfb4b..4dc0028 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
@@ -27,6 +28,7 @@
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 
+#define        SDHCI_CTRL_D3CD                 0x08
 /* VENDOR SPEC register */
 #define SDHCI_VENDOR_SPEC              0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK  0x00000002
@@ -141,13 +143,32 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct pltfm_imx_data *imx_data = pltfm_host->priv;
        struct esdhc_platform_data *boarddata = &imx_data->boarddata;
-
-       if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
-                       && (boarddata->cd_type == ESDHC_CD_GPIO)))
-               /*
-                * these interrupts won't work with a custom card_detect gpio
-                */
-               val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+       u32 data;
+
+       if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
+               if (boarddata->cd_type == ESDHC_CD_GPIO)
+                       /*
+                        * These interrupts won't work with a custom
+                        * card_detect gpio (only applied to mx25/35)
+                        */
+                       val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+
+               if (val & SDHCI_INT_CARD_INT) {
+                       /*
+                        * Clear and then set D3CD bit to avoid missing the
+                        * card interrupt.  This is a eSDHC controller problem
+                        * so we need to apply the following workaround: clear
+                        * and set D3CD bit will make eSDHC re-sample the card
+                        * interrupt. In case a card interrupt was lost,
+                        * re-sample it by the following steps.
+                        */
+                       data = readl(host->ioaddr + SDHCI_HOST_CONTROL);
+                       data &= ~SDHCI_CTRL_D3CD;
+                       writel(data, host->ioaddr + SDHCI_HOST_CONTROL);
+                       data |= SDHCI_CTRL_D3CD;
+                       writel(data, host->ioaddr + SDHCI_HOST_CONTROL);
+               }
+       }
 
        if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
                                && (reg == SDHCI_INT_STATUS)
@@ -217,8 +238,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
                 */
                return;
        case SDHCI_HOST_CONTROL:
-               /* FSL messed up here, so we can just keep those two */
-               new_val = val & (SDHCI_CTRL_LED | SDHCI_CTRL_4BITBUS);
+               /* FSL messed up here, so we can just keep those three */
+               new_val = val & (SDHCI_CTRL_LED | \
+                               SDHCI_CTRL_4BITBUS | \
+                               SDHCI_CTRL_D3CD);
                /* ensure the endianess */
                new_val |= ESDHC_HOST_CONTROL_LE;
                /* DMA mode bits are shifted */
index 4198dbb..fc7e4a5 100644 (file)
@@ -195,7 +195,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        clk_enable(clk);
 
        host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
-               | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
+               | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
+               | SDHCI_QUIRK_32BIT_ADMA_SIZE;
 
        /* enable 1/8V DDR capable */
        host->mmc->caps |= MMC_CAP_1_8V_DDR;
index 460ffaf..fe886d6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/module.h>
 
 #include <linux/mmc/host.h>
 
@@ -301,6 +302,8 @@ static int sdhci_s3c_platform_8bit_width(struct sdhci_host *host, int width)
                ctrl &= ~SDHCI_CTRL_8BITBUS;
                break;
        default:
+               ctrl &= ~SDHCI_CTRL_4BITBUS;
+               ctrl &= ~SDHCI_CTRL_8BITBUS;
                break;
        }
 
@@ -502,6 +505,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        /* This host supports the Auto CMD12 */
        host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
 
+       /* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */
+       host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC;
+
        if (pdata->cd_type == S3C_SDHCI_CD_NONE ||
            pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
                host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
index c31a334..0e02cc1 100644 (file)
@@ -628,12 +628,11 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
        /* timeout in us */
        if (!data)
                target_timeout = cmd->cmd_timeout_ms * 1000;
-       else
-               target_timeout = data->timeout_ns / 1000 +
-                       data->timeout_clks / host->clock;
-
-       if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-               host->timeout_clk = host->clock / 1000;
+       else {
+               target_timeout = data->timeout_ns / 1000;
+               if (host->clock)
+                       target_timeout += data->timeout_clks / host->clock;
+       }
 
        /*
         * Figure out needed cycles.
@@ -645,7 +644,6 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
         *     =>
         *     (1) / (2) > 2^6
         */
-       BUG_ON(!host->timeout_clk);
        count = 0;
        current_timeout = (1 << 13) * 1000 / host->timeout_clk;
        while (current_timeout < target_timeout) {
@@ -1867,9 +1865,6 @@ static void sdhci_tasklet_finish(unsigned long param)
 
        del_timer(&host->timer);
 
-       if (host->version >= SDHCI_SPEC_300)
-               del_timer(&host->tuning_timer);
-
        mrq = host->mrq;
 
        /*
@@ -2461,22 +2456,6 @@ int sdhci_add_host(struct sdhci_host *host)
                host->max_clk = host->ops->get_max_clock(host);
        }
 
-       host->timeout_clk =
-               (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
-       if (host->timeout_clk == 0) {
-               if (host->ops->get_timeout_clock) {
-                       host->timeout_clk = host->ops->get_timeout_clock(host);
-               } else if (!(host->quirks &
-                               SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
-                       printk(KERN_ERR
-                              "%s: Hardware doesn't specify timeout clock "
-                              "frequency.\n", mmc_hostname(mmc));
-                       return -ENODEV;
-               }
-       }
-       if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
-               host->timeout_clk *= 1000;
-
        /*
         * In case of Host Controller v3.00, find out whether clock
         * multiplier is supported.
@@ -2509,10 +2488,26 @@ int sdhci_add_host(struct sdhci_host *host)
        } else
                mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
+       host->timeout_clk =
+               (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
+       if (host->timeout_clk == 0) {
+               if (host->ops->get_timeout_clock) {
+                       host->timeout_clk = host->ops->get_timeout_clock(host);
+               } else if (!(host->quirks &
+                               SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
+                       printk(KERN_ERR
+                              "%s: Hardware doesn't specify timeout clock "
+                              "frequency.\n", mmc_hostname(mmc));
+                       return -ENODEV;
+               }
+       }
+       if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
+               host->timeout_clk *= 1000;
+
        if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-               mmc->max_discard_to = (1 << 27) / (mmc->f_max / 1000);
-       else
-               mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+               host->timeout_clk = mmc->f_max / 1000;
+
+       mmc->max_discard_to = (1 << 27) / host->timeout_clk;
 
        mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
 
index 774f643..0c4a672 100644 (file)
@@ -120,11 +120,11 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
        mmc_data->hclk = clk_get_rate(priv->clk);
        mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
        mmc_data->get_cd = sh_mobile_sdhi_get_cd;
-       if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT)
-               mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
        mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
        if (p) {
                mmc_data->flags = p->tmio_flags;
+               if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT)
+                       mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
                mmc_data->ocr_mask = p->tmio_ocr_mask;
                mmc_data->capabilities |= p->tmio_caps;
 
index 8d185de..44a9668 100644 (file)
@@ -27,7 +27,6 @@
 static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
 {
        const struct mfd_cell *cell = mfd_get_cell(dev);
-       struct mmc_host *mmc = platform_get_drvdata(dev);
        int ret;
 
        ret = tmio_mmc_host_suspend(&dev->dev);
@@ -42,7 +41,6 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
 static int tmio_mmc_resume(struct platform_device *dev)
 {
        const struct mfd_cell *cell = mfd_get_cell(dev);
-       struct mmc_host *mmc = platform_get_drvdata(dev);
        int ret = 0;
 
        /* Tell the MFD core we are ready to be enabled */
index 65b5b76..64fbb00 100644 (file)
@@ -181,7 +181,7 @@ static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
 
 #define ubi_dbg_msg(fmt, ...) do {                                           \
        if (0)                                                               \
-               pr_debug(fmt "\n", ##__VA_ARGS__);                           \
+               printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__);                  \
 } while (0)
 
 #define dbg_msg(fmt, ...)  ubi_dbg_msg(fmt, ##__VA_ARGS__)
index 52fe21e..3b1416e 100644 (file)
@@ -308,8 +308,11 @@ static void am79c961_timer(unsigned long data)
        struct net_device *dev = (struct net_device *)data;
        struct dev_priv *priv = netdev_priv(dev);
        unsigned int lnkstat, carrier;
+       unsigned long flags;
 
+       spin_lock_irqsave(&priv->chip_lock, flags);
        lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
+       spin_unlock_irqrestore(&priv->chip_lock, flags);
        carrier = netif_carrier_ok(dev);
 
        if (lnkstat && !carrier) {
index 38a83ac..43f2ea5 100644 (file)
@@ -3419,9 +3419,27 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
 static int bond_open(struct net_device *bond_dev)
 {
        struct bonding *bond = netdev_priv(bond_dev);
+       struct slave *slave;
+       int i;
 
        bond->kill_timers = 0;
 
+       /* reset slave->backup and slave->inactive */
+       read_lock(&bond->lock);
+       if (bond->slave_cnt > 0) {
+               read_lock(&bond->curr_slave_lock);
+               bond_for_each_slave(bond, slave, i) {
+                       if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+                               && (slave != bond->curr_active_slave)) {
+                               bond_set_slave_inactive_flags(slave);
+                       } else {
+                               bond_set_slave_active_flags(slave);
+                       }
+               }
+               read_unlock(&bond->curr_slave_lock);
+       }
+       read_unlock(&bond->lock);
+
        INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
 
        if (bond_is_lb(bond)) {
index 231385b..c7f3d4e 100644 (file)
@@ -408,7 +408,7 @@ static void plx_pci_del_card(struct pci_dev *pdev)
        struct sja1000_priv *priv;
        int i = 0;
 
-       for (i = 0; i < card->channels; i++) {
+       for (i = 0; i < PLX_PCI_MAX_CHAN; i++) {
                dev = card->net_dev[i];
                if (!dev)
                        continue;
@@ -536,7 +536,6 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev,
                        if (err) {
                                dev_err(&pdev->dev, "Registering device failed "
                                        "(err=%d)\n", err);
-                               free_sja1000dev(dev);
                                goto failure_cleanup;
                        }
 
@@ -549,6 +548,7 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev,
                        dev_err(&pdev->dev, "Channel #%d not detected\n",
                                i + 1);
                        free_sja1000dev(dev);
+                       card->net_dev[i] = NULL;
                }
        }
 
index f7bbde9..a812492 100644 (file)
@@ -503,9 +503,9 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
        spin_unlock_irqrestore(&priv->mbx_lock, flags);
 
        /* Prepare mailbox for transmission */
+       data = cf->can_dlc | (get_tx_head_prio(priv) << 8);
        if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */
                data |= HECC_CANMCF_RTR;
-       data |= get_tx_head_prio(priv) << 8;
        hecc_write_mbx(priv, mbxno, HECC_CANMCF, data);
 
        if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
@@ -923,6 +923,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
        priv->can.do_get_state = ti_hecc_get_state;
        priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
 
+       spin_lock_init(&priv->mbx_lock);
        ndev->irq = irq->start;
        ndev->flags |= IFF_ECHO;
        platform_set_drvdata(pdev, ndev);
index 646c86b..fdb7a17 100644 (file)
@@ -2452,14 +2452,13 @@ static irqreturn_t cas_interruptN(int irq, void *dev_id)
        struct net_device *dev = dev_id;
        struct cas *cp = netdev_priv(dev);
        unsigned long flags;
-       int ring;
+       int ring = (irq == cp->pci_irq_INTC) ? 2 : 3;
        u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(ring));
 
        /* check for shared irq */
        if (status == 0)
                return IRQ_NONE;
 
-       ring = (irq == cp->pci_irq_INTC) ? 2 : 3;
        spin_lock_irqsave(&cp->lock, flags);
        if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
 #ifdef USE_NAPI
index 35916f4..8533ad7 100644 (file)
@@ -155,6 +155,9 @@ struct e1000_info;
 #define HV_M_STATUS_SPEED_1000            0x0200
 #define HV_M_STATUS_LINK_UP               0x0040
 
+#define E1000_ICH_FWSM_PCIM2PCI                0x01000000 /* ME PCIm-to-PCI active */
+#define E1000_ICH_FWSM_PCIM2PCI_COUNT  2000
+
 /* Time to wait before putting the device into D3 if there's no link (in ms). */
 #define LINK_TIMEOUT           100
 
@@ -454,6 +457,7 @@ struct e1000_info {
 #define FLAG2_DISABLE_AIM                 (1 << 8)
 #define FLAG2_CHECK_PHY_HANG              (1 << 9)
 #define FLAG2_NO_DISABLE_RX               (1 << 10)
+#define FLAG2_PCIM2PCI_ARBITER_WA         (1 << 11)
 
 #define E1000_RX_DESC_PS(R, i)     \
        (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
index 4e36978..54add27 100644 (file)
 #define HV_PM_CTRL             PHY_REG(770, 17)
 
 /* PHY Low Power Idle Control */
-#define I82579_LPI_CTRL                        PHY_REG(772, 20)
-#define I82579_LPI_CTRL_ENABLE_MASK    0x6000
+#define I82579_LPI_CTRL                                PHY_REG(772, 20)
+#define I82579_LPI_CTRL_ENABLE_MASK            0x6000
+#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT   0x80
 
 /* EMI Registers */
 #define I82579_EMI_ADDR         0x10
 #define HV_KMRN_MODE_CTRL      PHY_REG(769, 16)
 #define HV_KMRN_MDIO_SLOW      0x0400
 
+/* KMRN FIFO Control and Status */
+#define HV_KMRN_FIFO_CTRLSTA                  PHY_REG(770, 16)
+#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK    0x7000
+#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT   12
+
 /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
 /* Offset 04h HSFSTS */
 union ich8_hws_flash_status {
@@ -657,6 +663,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val;
        bool link;
+       u16 phy_reg;
 
        /*
         * We only want to go out to the PHY registers to see if Auto-Neg
@@ -689,16 +696,35 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
 
        mac->get_link_status = false;
 
-       if (hw->phy.type == e1000_phy_82578) {
-               ret_val = e1000_link_stall_workaround_hv(hw);
-               if (ret_val)
-                       goto out;
-       }
-
-       if (hw->mac.type == e1000_pch2lan) {
+       switch (hw->mac.type) {
+       case e1000_pch2lan:
                ret_val = e1000_k1_workaround_lv(hw);
                if (ret_val)
                        goto out;
+               /* fall-thru */
+       case e1000_pchlan:
+               if (hw->phy.type == e1000_phy_82578) {
+                       ret_val = e1000_link_stall_workaround_hv(hw);
+                       if (ret_val)
+                               goto out;
+               }
+
+               /*
+                * Workaround for PCHx parts in half-duplex:
+                * Set the number of preambles removed from the packet
+                * when it is passed from the PHY to the MAC to prevent
+                * the MAC from misinterpreting the packet type.
+                */
+               e1e_rphy(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg);
+               phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK;
+
+               if ((er32(STATUS) & E1000_STATUS_FD) != E1000_STATUS_FD)
+                       phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT);
+
+               e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg);
+               break;
+       default:
+               break;
        }
 
        /*
@@ -788,6 +814,11 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
            (adapter->hw.phy.type == e1000_phy_igp_3))
                adapter->flags |= FLAG_LSC_GIG_SPEED_DROP;
 
+       /* Enable workaround for 82579 w/ ME enabled */
+       if ((adapter->hw.mac.type == e1000_pch2lan) &&
+           (er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
+               adapter->flags2 |= FLAG2_PCIM2PCI_ARBITER_WA;
+
        /* Disable EEE by default until IEEE802.3az spec is finalized */
        if (adapter->flags2 & FLAG2_HAS_EEE)
                adapter->hw.dev_spec.ich8lan.eee_disable = true;
@@ -1355,7 +1386,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
                        return ret_val;
 
                /* Preamble tuning for SSC */
-               ret_val = e1e_wphy(hw, PHY_REG(770, 16), 0xA204);
+               ret_val = e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204);
                if (ret_val)
                        return ret_val;
        }
@@ -1645,6 +1676,7 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
        s32 ret_val = 0;
        u16 status_reg = 0;
        u32 mac_reg;
+       u16 phy_reg;
 
        if (hw->mac.type != e1000_pch2lan)
                goto out;
@@ -1659,12 +1691,19 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
                mac_reg = er32(FEXTNVM4);
                mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
 
-               if (status_reg & HV_M_STATUS_SPEED_1000)
+               ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
+               if (ret_val)
+                       goto out;
+
+               if (status_reg & HV_M_STATUS_SPEED_1000) {
                        mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
-               else
+                       phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+               } else {
                        mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
-
+                       phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+               }
                ew32(FEXTNVM4, mac_reg);
+               ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
        }
 
 out:
index 362f703..2198e61 100644 (file)
@@ -518,6 +518,63 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
        adapter->hw_csum_good++;
 }
 
+/**
+ * e1000e_update_tail_wa - helper function for e1000e_update_[rt]dt_wa()
+ * @hw: pointer to the HW structure
+ * @tail: address of tail descriptor register
+ * @i: value to write to tail descriptor register
+ *
+ * When updating the tail register, the ME could be accessing Host CSR
+ * registers at the same time.  Normally, this is handled in h/w by an
+ * arbiter but on some parts there is a bug that acknowledges Host accesses
+ * later than it should which could result in the descriptor register to
+ * have an incorrect value.  Workaround this by checking the FWSM register
+ * which has bit 24 set while ME is accessing Host CSR registers, wait
+ * if it is set and try again a number of times.
+ **/
+static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, u8 __iomem * tail,
+                                       unsigned int i)
+{
+       unsigned int j = 0;
+
+       while ((j++ < E1000_ICH_FWSM_PCIM2PCI_COUNT) &&
+              (er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI))
+               udelay(50);
+
+       writel(i, tail);
+
+       if ((j == E1000_ICH_FWSM_PCIM2PCI_COUNT) && (i != readl(tail)))
+               return E1000_ERR_SWFW_SYNC;
+
+       return 0;
+}
+
+static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i)
+{
+       u8 __iomem *tail = (adapter->hw.hw_addr + adapter->rx_ring->tail);
+       struct e1000_hw *hw = &adapter->hw;
+
+       if (e1000e_update_tail_wa(hw, tail, i)) {
+               u32 rctl = er32(RCTL);
+               ew32(RCTL, rctl & ~E1000_RCTL_EN);
+               e_err("ME firmware caused invalid RDT - resetting\n");
+               schedule_work(&adapter->reset_task);
+       }
+}
+
+static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i)
+{
+       u8 __iomem *tail = (adapter->hw.hw_addr + adapter->tx_ring->tail);
+       struct e1000_hw *hw = &adapter->hw;
+
+       if (e1000e_update_tail_wa(hw, tail, i)) {
+               u32 tctl = er32(TCTL);
+               ew32(TCTL, tctl & ~E1000_TCTL_EN);
+               e_err("ME firmware caused invalid TDT - resetting\n");
+               schedule_work(&adapter->reset_task);
+       }
+}
+
 /**
  * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
  * @adapter: address of board private structure
@@ -573,7 +630,10 @@ map_skb:
                         * such as IA-64).
                         */
                        wmb();
-                       writel(i, adapter->hw.hw_addr + rx_ring->tail);
+                       if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+                               e1000e_update_rdt_wa(adapter, i);
+                       else
+                               writel(i, adapter->hw.hw_addr + rx_ring->tail);
                }
                i++;
                if (i == rx_ring->count)
@@ -673,7 +733,11 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
                         * such as IA-64).
                         */
                        wmb();
-                       writel(i << 1, adapter->hw.hw_addr + rx_ring->tail);
+                       if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+                               e1000e_update_rdt_wa(adapter, i << 1);
+                       else
+                               writel(i << 1,
+                                      adapter->hw.hw_addr + rx_ring->tail);
                }
 
                i++;
@@ -756,7 +820,10 @@ check_page:
                 * applicable for weak-ordered memory model archs,
                 * such as IA-64). */
                wmb();
-               writel(i, adapter->hw.hw_addr + rx_ring->tail);
+               if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+                       e1000e_update_rdt_wa(adapter, i);
+               else
+                       writel(i, adapter->hw.hw_addr + rx_ring->tail);
        }
 }
 
@@ -4689,7 +4756,12 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
        wmb();
 
        tx_ring->next_to_use = i;
-       writel(i, adapter->hw.hw_addr + tx_ring->tail);
+
+       if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+               e1000e_update_tdt_wa(adapter, i);
+       else
+               writel(i, adapter->hw.hw_addr + tx_ring->tail);
+
        /*
         * we need this if more than one processor can write to our tail
         * at a time, it synchronizes IO on IA64/Altix systems
index e55df30..6d5fbd4 100644 (file)
@@ -5615,7 +5615,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                goto out_error;
        }
 
-       nv_vlan_mode(dev, dev->features);
+       if (id->driver_data & DEV_HAS_VLAN)
+               nv_vlan_mode(dev, dev->features);
 
        netif_carrier_off(dev);
 
index 2659daa..31d5c57 100644 (file)
@@ -2710,8 +2710,13 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
        /* Tell the skb what kind of packet this is */
        skb->protocol = eth_type_trans(skb, dev);
 
-       /* Set vlan tag */
-       if (fcb->flags & RXFCB_VLN)
+       /*
+        * There's need to check for NETIF_F_HW_VLAN_RX here.
+        * Even if vlan rx accel is disabled, on some chips
+        * RXFCB_VLN is pseudo randomly set.
+        */
+       if (dev->features & NETIF_F_HW_VLAN_RX &&
+           fcb->flags & RXFCB_VLN)
                __vlan_hwaccel_put_tag(skb, fcb->vlctl);
 
        /* Send the packet up the stack */
index 6e35069..25a8c2a 100644 (file)
@@ -686,10 +686,21 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
 {
        unsigned int last_rule_idx = priv->cur_filer_idx;
        unsigned int cmp_rqfpr;
-       unsigned int local_rqfpr[MAX_FILER_IDX + 1];
-       unsigned int local_rqfcr[MAX_FILER_IDX + 1];
+       unsigned int *local_rqfpr;
+       unsigned int *local_rqfcr;
        int i = 0x0, k = 0x0;
        int j = MAX_FILER_IDX, l = 0x0;
+       int ret = 1;
+
+       local_rqfpr = kmalloc(sizeof(unsigned int) * (MAX_FILER_IDX + 1),
+               GFP_KERNEL);
+       local_rqfcr = kmalloc(sizeof(unsigned int) * (MAX_FILER_IDX + 1),
+               GFP_KERNEL);
+       if (!local_rqfpr || !local_rqfcr) {
+               pr_err("Out of memory\n");
+               ret = 0;
+               goto err;
+       }
 
        switch (class) {
        case TCP_V4_FLOW:
@@ -706,7 +717,8 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
                break;
        default:
                pr_err("Right now this class is not supported\n");
-               return 0;
+               ret = 0;
+               goto err;
        }
 
        for (i = 0; i < MAX_FILER_IDX + 1; i++) {
@@ -721,7 +733,8 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
 
        if (i == MAX_FILER_IDX + 1) {
                pr_err("No parse rule found, can't create hash rules\n");
-               return 0;
+               ret = 0;
+               goto err;
        }
 
        /* If a match was found, then it begins the starting of a cluster rule
@@ -765,7 +778,10 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
                priv->cur_filer_idx = priv->cur_filer_idx - 1;
        }
 
-       return 1;
+err:
+       kfree(local_rqfcr);
+       kfree(local_rqfpr);
+       return ret;
 }
 
 static int gfar_set_hash_opts(struct gfar_private *priv, struct ethtool_rxnfc *cmd)
index ba99af0..3e66792 100644 (file)
@@ -395,7 +395,7 @@ static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *ada
 }
 
 /* recycle the current buffer on the rx queue */
-static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
+static int ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
 {
        u32 q_index = adapter->rx_queue.index;
        u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator;
@@ -403,6 +403,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
        unsigned int index = correlator & 0xffffffffUL;
        union ibmveth_buf_desc desc;
        unsigned long lpar_rc;
+       int ret = 1;
 
        BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
        BUG_ON(index >= adapter->rx_buff_pool[pool].size);
@@ -410,7 +411,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
        if (!adapter->rx_buff_pool[pool].active) {
                ibmveth_rxq_harvest_buffer(adapter);
                ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]);
-               return;
+               goto out;
        }
 
        desc.fields.flags_len = IBMVETH_BUF_VALID |
@@ -423,12 +424,16 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
                netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed "
                           "during recycle rc=%ld", lpar_rc);
                ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
+               ret = 0;
        }
 
        if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
                adapter->rx_queue.index = 0;
                adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
        }
+
+out:
+       return ret;
 }
 
 static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter)
@@ -1084,8 +1089,9 @@ restart_poll:
                                if (rx_flush)
                                        ibmveth_flush_buffer(skb->data,
                                                length + offset);
+                               if (!ibmveth_rxq_recycle_buffer(adapter))
+                                       kfree_skb(skb);
                                skb = new_skb;
-                               ibmveth_rxq_recycle_buffer(adapter);
                        } else {
                                ibmveth_rxq_harvest_buffer(adapter);
                                skb_reserve(skb, offset);
index e86297b..2279039 100644 (file)
@@ -1459,8 +1459,10 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                if (ixgbe_rx_is_fcoe(adapter, rx_desc)) {
                        ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb,
                                                   staterr);
-                       if (!ddp_bytes)
+                       if (!ddp_bytes) {
+                               dev_kfree_skb_any(skb);
                                goto next_desc;
+                       }
                }
 #endif /* IXGBE_FCOE */
                ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc);
index 0620ba9..04bb8fc 100644 (file)
@@ -25,8 +25,9 @@
 /* DP83865 phy identifier values */
 #define DP83865_PHY_ID 0x20005c7a
 
-#define DP83865_INT_MASK_REG 0x15
-#define DP83865_INT_MASK_STATUS 0x14
+#define DP83865_INT_STATUS     0x14
+#define DP83865_INT_MASK       0x15
+#define DP83865_INT_CLEAR      0x17
 
 #define DP83865_INT_REMOTE_FAULT 0x0008
 #define DP83865_INT_ANE_COMPLETED 0x0010
@@ -68,21 +69,25 @@ static int ns_config_intr(struct phy_device *phydev)
        int err;
 
        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
-               err = phy_write(phydev, DP83865_INT_MASK_REG,
+               err = phy_write(phydev, DP83865_INT_MASK,
                                DP83865_INT_MASK_DEFAULT);
        else
-               err = phy_write(phydev, DP83865_INT_MASK_REG, 0);
+               err = phy_write(phydev, DP83865_INT_MASK, 0);
 
        return err;
 }
 
 static int ns_ack_interrupt(struct phy_device *phydev)
 {
-       int ret = phy_read(phydev, DP83865_INT_MASK_STATUS);
+       int ret = phy_read(phydev, DP83865_INT_STATUS);
        if (ret < 0)
                return ret;
 
-       return 0;
+       /* Clear the interrupt status bit by writing a “1”
+        * to the corresponding bit in INT_CLEAR (2:0 are reserved) */
+       ret = phy_write(phydev, DP83865_INT_CLEAR, ret & ~0x7);
+
+       return ret;
 }
 
 static void ns_giga_speed_fallback(struct phy_device *phydev, int mode)
index 86ac38c..3bb1311 100644 (file)
@@ -80,13 +80,13 @@ static int rionet_capable = 1;
  */
 static struct rio_dev **rionet_active;
 
-#define is_rionet_capable(pef, src_ops, dst_ops)               \
-                       ((pef & RIO_PEF_INB_MBOX) &&            \
-                        (pef & RIO_PEF_INB_DOORBELL) &&        \
+#define is_rionet_capable(src_ops, dst_ops)                    \
+                       ((src_ops & RIO_SRC_OPS_DATA_MSG) &&    \
+                        (dst_ops & RIO_DST_OPS_DATA_MSG) &&    \
                         (src_ops & RIO_SRC_OPS_DOORBELL) &&    \
                         (dst_ops & RIO_DST_OPS_DOORBELL))
 #define dev_rionet_capable(dev) \
-       is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
+       is_rionet_capable(dev->src_ops, dev->dst_ops)
 
 #define RIONET_MAC_MATCH(x)    (*(u32 *)x == 0x00010001)
 #define RIONET_GET_DESTID(x)   (*(u16 *)(x + 4))
@@ -282,7 +282,6 @@ static int rionet_open(struct net_device *ndev)
 {
        int i, rc = 0;
        struct rionet_peer *peer, *tmp;
-       u32 pwdcsr;
        struct rionet_private *rnet = netdev_priv(ndev);
 
        if (netif_msg_ifup(rnet))
@@ -332,13 +331,8 @@ static int rionet_open(struct net_device *ndev)
                        continue;
                }
 
-               /*
-                * If device has initialized inbound doorbells,
-                * send a join message
-                */
-               rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
-               if (pwdcsr & RIO_DOORBELL_AVAIL)
-                       rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
+               /* Send a join message */
+               rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
        }
 
       out:
@@ -492,7 +486,7 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
 static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
 {
        int rc = -ENODEV;
-       u32 lpef, lsrc_ops, ldst_ops;
+       u32 lsrc_ops, ldst_ops;
        struct rionet_peer *peer;
        struct net_device *ndev = NULL;
 
@@ -515,12 +509,11 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
         * on later probes
         */
        if (!rionet_check) {
-               rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
                rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
                                         &lsrc_ops);
                rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
                                         &ldst_ops);
-               if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
+               if (!is_rionet_capable(lsrc_ops, ldst_ops)) {
                        printk(KERN_ERR
                               "%s: local device is not network capable\n",
                               DRV_NAME);
index ad35c21..1c1666e 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
@@ -30,6 +31,7 @@
 #include <linux/phy.h>
 #include <linux/cache.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/ethtool.h>
index a03336e..f06fb78 100644 (file)
@@ -228,23 +228,40 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
        if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
 
                if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) {
-                       struct usb_cdc_ncm_ndp_input_size ndp_in_sz;
+                       struct usb_cdc_ncm_ndp_input_size *ndp_in_sz;
+
+                       ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL);
+                       if (!ndp_in_sz) {
+                               err = -ENOMEM;
+                               goto size_err;
+                       }
+
                        err = usb_control_msg(ctx->udev,
                                        usb_sndctrlpipe(ctx->udev, 0),
                                        USB_CDC_SET_NTB_INPUT_SIZE,
                                        USB_TYPE_CLASS | USB_DIR_OUT
                                         | USB_RECIP_INTERFACE,
-                                       0, iface_no, &ndp_in_sz, 8, 1000);
+                                       0, iface_no, ndp_in_sz, 8, 1000);
+                       kfree(ndp_in_sz);
                } else {
-                       __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+                       __le32 *dwNtbInMaxSize;
+                       dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize),
+                                       GFP_KERNEL);
+                       if (!dwNtbInMaxSize) {
+                               err = -ENOMEM;
+                               goto size_err;
+                       }
+                       *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+
                        err = usb_control_msg(ctx->udev,
                                        usb_sndctrlpipe(ctx->udev, 0),
                                        USB_CDC_SET_NTB_INPUT_SIZE,
                                        USB_TYPE_CLASS | USB_DIR_OUT
                                         | USB_RECIP_INTERFACE,
-                                       0, iface_no, &dwNtbInMaxSize, 4, 1000);
+                                       0, iface_no, dwNtbInMaxSize, 4, 1000);
+                       kfree(dwNtbInMaxSize);
                }
-
+size_err:
                if (err < 0)
                        pr_debug("Setting NTB Input Size failed\n");
        }
@@ -325,19 +342,29 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 
        /* set Max Datagram Size (MTU) */
        if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
-               __le16 max_datagram_size;
+               __le16 *max_datagram_size;
                u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+
+               max_datagram_size = kzalloc(sizeof(*max_datagram_size),
+                               GFP_KERNEL);
+               if (!max_datagram_size) {
+                       err = -ENOMEM;
+                       goto max_dgram_err;
+               }
+
                err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0),
                                USB_CDC_GET_MAX_DATAGRAM_SIZE,
                                USB_TYPE_CLASS | USB_DIR_IN
                                 | USB_RECIP_INTERFACE,
-                               0, iface_no, &max_datagram_size,
+                               0, iface_no, max_datagram_size,
                                2, 1000);
                if (err < 0) {
                        pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
                                                CDC_NCM_MIN_DATAGRAM_SIZE);
+                       kfree(max_datagram_size);
                } else {
-                       ctx->max_datagram_size = le16_to_cpu(max_datagram_size);
+                       ctx->max_datagram_size =
+                               le16_to_cpu(*max_datagram_size);
                        /* Check Eth descriptor value */
                        if (eth_max_sz < CDC_NCM_MAX_DATAGRAM_SIZE) {
                                if (ctx->max_datagram_size > eth_max_sz)
@@ -360,8 +387,10 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
                                                USB_TYPE_CLASS | USB_DIR_OUT
                                                 | USB_RECIP_INTERFACE,
                                                0,
-                                               iface_no, &max_datagram_size,
+                                               iface_no, max_datagram_size,
                                                2, 1000);
+                       kfree(max_datagram_size);
+max_dgram_err:
                        if (err < 0)
                                pr_debug("SET_MAX_DATAGRAM_SIZE failed\n");
                }
index deb1eca..7c5336c 100644 (file)
@@ -515,10 +515,6 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
        mac_set_cam_mask(regs, vptr->mCAMmask);
 
        /* Enable VCAMs */
-
-       if (test_bit(0, vptr->active_vlans))
-               WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
-
        for_each_set_bit(vid, vptr->active_vlans, VLAN_N_VID) {
                mac_set_vlan_cam(regs, i, (u8 *) &vid);
                vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
index 1cbacb3..0959583 100644 (file)
@@ -1929,14 +1929,17 @@ static void
 vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
-       u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
-       unsigned long flags;
 
-       VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
-       spin_lock_irqsave(&adapter->cmd_lock, flags);
-       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
-                              VMXNET3_CMD_UPDATE_VLAN_FILTERS);
-       spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       if (!(netdev->flags & IFF_PROMISC)) {
+               u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+               unsigned long flags;
+
+               VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                      VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       }
 
        set_bit(vid, adapter->active_vlans);
 }
@@ -1946,14 +1949,17 @@ static void
 vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
-       u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
-       unsigned long flags;
 
-       VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
-       spin_lock_irqsave(&adapter->cmd_lock, flags);
-       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
-                              VMXNET3_CMD_UPDATE_VLAN_FILTERS);
-       spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       if (!(netdev->flags & IFF_PROMISC)) {
+               u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+               unsigned long flags;
+
+               VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                      VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       }
 
        clear_bit(vid, adapter->active_vlans);
 }
index c34bef1..1b94003 100644 (file)
@@ -69,7 +69,7 @@ static int ar9003_hw_power_interpolate(int32_t x,
 static const struct ar9300_eeprom ar9300_default = {
        .eepromVersion = 2,
        .templateVersion = 2,
-       .macAddr = {1, 2, 3, 4, 5, 6},
+       .macAddr = {0, 2, 3, 4, 5, 6},
        .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        .baseEepHeader = {
index 9098aaa..6530694 100644 (file)
@@ -2283,7 +2283,11 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 
        mutex_lock(&sc->mutex);
        ah->coverage_class = coverage_class;
+
+       ath9k_ps_wakeup(sc);
        ath9k_hw_init_global_settings(ah);
+       ath9k_ps_restore(sc);
+
        mutex_unlock(&sc->mutex);
 }
 
index 0122930..0474e66 100644 (file)
@@ -1066,8 +1066,10 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
         * the high througput speed in 802.11n networks.
         */
 
-       if (!is_main_vif(ar, vif))
+       if (!is_main_vif(ar, vif)) {
+               mutex_lock(&ar->mutex);
                goto err_softw;
+       }
 
        /*
         * While the hardware supports *catch-all* key, for offloading
index 69d4ec4..2fdbffa 100644 (file)
@@ -478,27 +478,22 @@ out_no_pci:
        return err;
 }
 
-static void iwl_pci_down(struct iwl_bus *bus)
-{
-       struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific;
-
-       pci_disable_msi(pci_bus->pci_dev);
-       pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base);
-       pci_release_regions(pci_bus->pci_dev);
-       pci_disable_device(pci_bus->pci_dev);
-       pci_set_drvdata(pci_bus->pci_dev, NULL);
-
-       kfree(bus);
-}
-
 static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 {
        struct iwl_priv *priv = pci_get_drvdata(pdev);
-       void *bus_specific = priv->bus->bus_specific;
+       struct iwl_bus *bus = priv->bus;
+       struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus);
+       struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
 
        iwl_remove(priv);
 
-       iwl_pci_down(bus_specific);
+       pci_disable_msi(pci_dev);
+       pci_iounmap(pci_dev, pci_bus->hw_base);
+       pci_release_regions(pci_dev);
+       pci_disable_device(pci_dev);
+       pci_set_drvdata(pci_dev, NULL);
+
+       kfree(bus);
 }
 
 #ifdef CONFIG_PM
index 9395631..dbf501c 100644 (file)
@@ -464,6 +464,15 @@ static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
        int wcid, ack, pid;
        int tx_wcid, tx_ack, tx_pid;
 
+       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
+               WARNING(entry->queue->rt2x00dev,
+                       "Data pending for entry %u in queue %u\n",
+                       entry->entry_idx, entry->queue->qid);
+               cond_resched();
+               return false;
+       }
+
        wcid    = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
        ack     = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
        pid     = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
@@ -529,12 +538,11 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
                        entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                        if (rt2800usb_txdone_entry_check(entry, reg))
                                break;
+                       entry = NULL;
                }
 
-               if (!entry || rt2x00queue_empty(queue))
-                       break;
-
-               rt2800_txdone_entry(entry, reg);
+               if (entry)
+                       rt2800_txdone_entry(entry, reg);
        }
 }
 
@@ -558,8 +566,10 @@ static void rt2800usb_work_txdone(struct work_struct *work)
                while (!rt2x00queue_empty(queue)) {
                        entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 
-                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+                           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
                                break;
+
                        if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
                                rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
                        else if (rt2x00queue_status_timeout(entry))
index b6b4542..1e31050 100644 (file)
@@ -262,23 +262,20 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
        struct queue_entry *entry = (struct queue_entry *)urb->context;
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 
-       if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
                return;
-
-       if (rt2x00dev->ops->lib->tx_dma_done)
-               rt2x00dev->ops->lib->tx_dma_done(entry);
-
-       /*
-        * Report the frame as DMA done
-        */
-       rt2x00lib_dmadone(entry);
-
        /*
         * Check if the frame was correctly uploaded
         */
        if (urb->status)
                set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+       /*
+        * Report the frame as DMA done
+        */
+       rt2x00lib_dmadone(entry);
 
+       if (rt2x00dev->ops->lib->tx_dma_done)
+               rt2x00dev->ops->lib->tx_dma_done(entry);
        /*
         * Schedule the delayed work for reading the TX status
         * from the device.
@@ -874,18 +871,8 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
 {
        struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
        struct rt2x00_dev *rt2x00dev = hw->priv;
-       int retval;
-
-       retval = rt2x00lib_suspend(rt2x00dev, state);
-       if (retval)
-               return retval;
 
-       /*
-        * Decrease usbdev refcount.
-        */
-       usb_put_dev(interface_to_usbdev(usb_intf));
-
-       return 0;
+       return rt2x00lib_suspend(rt2x00dev, state);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_suspend);
 
@@ -894,8 +881,6 @@ int rt2x00usb_resume(struct usb_interface *usb_intf)
        struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
        struct rt2x00_dev *rt2x00dev = hw->priv;
 
-       usb_get_dev(interface_to_usbdev(usb_intf));
-
        return rt2x00lib_resume(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_resume);
index 7e33f1f..34f6ab5 100644 (file)
@@ -77,8 +77,6 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
        auth->sleep_auth = sleep_auth;
 
        ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
-       if (ret < 0)
-               return ret;
 
 out:
        kfree(auth);
@@ -624,10 +622,8 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl)
 
        ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
                                   detection, sizeof(*detection));
-       if (ret < 0) {
+       if (ret < 0)
                wl1271_warning("failed to set cca threshold: %d", ret);
-               return ret;
-       }
 
 out:
        kfree(detection);
index e58c22d..b70ae40 100644 (file)
@@ -4283,6 +4283,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
        wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
        wl->hw->wiphy->max_scan_ssids = 1;
+       wl->hw->wiphy->max_sched_scan_ssids = 1;
        /*
         * Maximum length of elements in scanning probe request templates
         * should be the maximum length possible for a template, without
index 5cf18c2..fb1fd5a 100644 (file)
@@ -164,7 +164,7 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
        /* If enabled, tell runtime PM not to power off the card */
        if (pm_runtime_enabled(&func->dev)) {
                ret = pm_runtime_get_sync(&func->dev);
-               if (ret)
+               if (ret < 0)
                        goto out;
        } else {
                /* Runtime PM is disabled: power up the card manually */
index 5d5e1ef..4ae8eff 100644 (file)
@@ -36,7 +36,6 @@ enum wl1271_tm_commands {
        WL1271_TM_CMD_TEST,
        WL1271_TM_CMD_INTERROGATE,
        WL1271_TM_CMD_CONFIGURE,
-       WL1271_TM_CMD_NVS_PUSH,
        WL1271_TM_CMD_SET_PLT_MODE,
        WL1271_TM_CMD_RECOVER,
 
@@ -139,12 +138,15 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
 
        if (ret < 0) {
                wl1271_warning("testmode cmd interrogate failed: %d", ret);
+               kfree(cmd);
                return ret;
        }
 
        skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd));
-       if (!skb)
+       if (!skb) {
+               kfree(cmd);
                return -ENOMEM;
+       }
 
        NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd);
 
@@ -187,48 +189,6 @@ static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
        return 0;
 }
 
-static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
-{
-       int ret = 0;
-       size_t len;
-       void *buf;
-
-       wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push");
-
-       if (!tb[WL1271_TM_ATTR_DATA])
-               return -EINVAL;
-
-       buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
-       len = nla_len(tb[WL1271_TM_ATTR_DATA]);
-
-       mutex_lock(&wl->mutex);
-
-       kfree(wl->nvs);
-
-       if ((wl->chip.id == CHIP_ID_1283_PG20) &&
-           (len != sizeof(struct wl128x_nvs_file)))
-               return -EINVAL;
-       else if (len != sizeof(struct wl1271_nvs_file))
-               return -EINVAL;
-
-       wl->nvs = kzalloc(len, GFP_KERNEL);
-       if (!wl->nvs) {
-               wl1271_error("could not allocate memory for the nvs file");
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       memcpy(wl->nvs, buf, len);
-       wl->nvs_len = len;
-
-       wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
-
-out:
-       mutex_unlock(&wl->mutex);
-
-       return ret;
-}
-
 static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
 {
        u32 val;
@@ -285,8 +245,6 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
                return wl1271_tm_cmd_interrogate(wl, tb);
        case WL1271_TM_CMD_CONFIGURE:
                return wl1271_tm_cmd_configure(wl, tb);
-       case WL1271_TM_CMD_NVS_PUSH:
-               return wl1271_tm_cmd_nvs_push(wl, tb);
        case WL1271_TM_CMD_SET_PLT_MODE:
                return wl1271_tm_cmd_set_plt_mode(wl, tb);
        case WL1271_TM_CMD_RECOVER:
index 749fdf0..3ffd9c1 100644 (file)
@@ -158,47 +158,6 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
         */
 }
 
-/* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */
-static int pci_set_payload(struct pci_dev *dev)
-{
-       int pos, ppos;
-       u16 pctl, psz;
-       u16 dctl, dsz, dcap, dmax;
-       struct pci_dev *parent;
-
-       parent = dev->bus->self;
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (!pos)
-               return 0;
-
-       /* Read Device MaxPayload capability and setting */
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl);
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap);
-       dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
-       dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD);
-
-       /* Read Parent MaxPayload setting */
-       ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
-       if (!ppos)
-               return 0;
-       pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
-       psz = (pctl &  PCI_EXP_DEVCTL_PAYLOAD) >> 5;
-
-       /* If parent payload > device max payload -> error
-        * If parent payload > device payload -> set speed
-        * If parent payload <= device payload -> do nothing
-        */
-       if (psz > dmax)
-               return -1;
-       else if (psz > dsz) {
-               dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz);
-               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
-                                     (dctl & ~PCI_EXP_DEVCTL_PAYLOAD) +
-                                     (psz << 5));
-       }
-       return 0;
-}
-
 void pci_configure_slot(struct pci_dev *dev)
 {
        struct pci_dev *cdev;
@@ -210,9 +169,9 @@ void pci_configure_slot(struct pci_dev *dev)
                        (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
                return;
 
-       ret = pci_set_payload(dev);
-       if (ret)
-               dev_warn(&dev->dev, "could not set device max payload\n");
+       if (dev->bus && dev->bus->self)
+               pcie_bus_configure_settings(dev->bus,
+                                           dev->bus->self->pcie_mpss);
 
        memset(&hpp, 0, sizeof(hpp));
        ret = pci_get_hp_params(dev, &hpp);
index c94d37e..f092993 100644 (file)
@@ -55,7 +55,7 @@ struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
         */
        if (bus->bridge->of_node)
                return of_node_get(bus->bridge->of_node);
-       if (bus->bridge->parent->of_node)
+       if (bus->bridge->parent && bus->bridge->parent->of_node)
                return of_node_get(bus->bridge->parent->of_node);
        return NULL;
 }
index 08a95b3..4e84fd4 100644 (file)
@@ -77,6 +77,8 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
 unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
 unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
 
+enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_SAFE;
+
 /*
  * The default CLS is used if arch didn't set CLS explicitly and not
  * all pci devices agree on the same value.  Arch can override either
@@ -3222,6 +3224,67 @@ out:
 }
 EXPORT_SYMBOL(pcie_set_readrq);
 
+/**
+ * pcie_get_mps - get PCI Express maximum payload size
+ * @dev: PCI device to query
+ *
+ * Returns maximum payload size in bytes
+ *    or appropriate error value.
+ */
+int pcie_get_mps(struct pci_dev *dev)
+{
+       int ret, cap;
+       u16 ctl;
+
+       cap = pci_pcie_cap(dev);
+       if (!cap)
+               return -EINVAL;
+
+       ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+       if (!ret)
+               ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+
+       return ret;
+}
+
+/**
+ * pcie_set_mps - set PCI Express maximum payload size
+ * @dev: PCI device to query
+ * @mps: maximum payload size in bytes
+ *    valid values are 128, 256, 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum payload size
+ */
+int pcie_set_mps(struct pci_dev *dev, int mps)
+{
+       int cap, err = -EINVAL;
+       u16 ctl, v;
+
+       if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
+               goto out;
+
+       v = ffs(mps) - 8;
+       if (v > dev->pcie_mpss) 
+               goto out;
+       v <<= 5;
+
+       cap = pci_pcie_cap(dev);
+       if (!cap)
+               goto out;
+
+       err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+       if (err)
+               goto out;
+
+       if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) {
+               ctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
+               ctl |= v;
+               err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
+       }
+out:
+       return err;
+}
+
 /**
  * pci_select_bars - Make BAR mask from the type of resource
  * @dev: the PCI device for which BAR mask is made
@@ -3505,6 +3568,10 @@ static int __init pci_setup(char *str)
                                pci_hotplug_io_size = memparse(str + 9, &str);
                        } else if (!strncmp(str, "hpmemsize=", 10)) {
                                pci_hotplug_mem_size = memparse(str + 10, &str);
+                       } else if (!strncmp(str, "pcie_bus_safe", 13)) {
+                               pcie_bus_config = PCIE_BUS_SAFE;
+                       } else if (!strncmp(str, "pcie_bus_perf", 13)) {
+                               pcie_bus_config = PCIE_BUS_PERFORMANCE;
                        } else {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);
index c8cee76..b74084e 100644 (file)
@@ -283,6 +283,8 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
 
 #endif /* CONFIG_PCI_IOV */
 
+extern unsigned long pci_cardbus_resource_alignment(struct resource *);
+
 static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
                                         struct resource *res)
 {
@@ -292,6 +294,8 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
        if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
                return pci_sriov_resource_alignment(dev, resno);
 #endif
+       if (dev->class >> 8  == PCI_CLASS_BRIDGE_CARDBUS)
+               return pci_cardbus_resource_alignment(res);
        return resource_alignment(res);
 }
 
index 795c902..b1187ff 100644 (file)
@@ -856,6 +856,8 @@ void set_pcie_port_type(struct pci_dev *pdev)
        pdev->pcie_cap = pos;
        pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
        pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
+       pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
+       pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
 }
 
 void set_pcie_hotplug_bridge(struct pci_dev *pdev)
@@ -1326,6 +1328,150 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
        return nr;
 }
 
+static int pcie_find_smpss(struct pci_dev *dev, void *data)
+{
+       u8 *smpss = data;
+
+       if (!pci_is_pcie(dev))
+               return 0;
+
+       /* For PCIE hotplug enabled slots not connected directly to a
+        * PCI-E root port, there can be problems when hotplugging
+        * devices.  This is due to the possibility of hotplugging a
+        * device into the fabric with a smaller MPS that the devices
+        * currently running have configured.  Modifying the MPS on the
+        * running devices could cause a fatal bus error due to an
+        * incoming frame being larger than the newly configured MPS.
+        * To work around this, the MPS for the entire fabric must be
+        * set to the minimum size.  Any devices hotplugged into this
+        * fabric will have the minimum MPS set.  If the PCI hotplug
+        * slot is directly connected to the root port and there are not
+        * other devices on the fabric (which seems to be the most
+        * common case), then this is not an issue and MPS discovery
+        * will occur as normal.
+        */
+       if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) ||
+           dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT))
+               *smpss = 0;
+
+       if (*smpss > dev->pcie_mpss)
+               *smpss = dev->pcie_mpss;
+
+       return 0;
+}
+
+static void pcie_write_mps(struct pci_dev *dev, int mps)
+{
+       int rc, dev_mpss;
+
+       dev_mpss = 128 << dev->pcie_mpss;
+
+       if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
+               if (dev->bus->self) {
+                       dev_dbg(&dev->bus->dev, "Bus MPSS %d\n",
+                               128 << dev->bus->self->pcie_mpss);
+
+                       /* For "MPS Force Max", the assumption is made that
+                        * downstream communication will never be larger than
+                        * the MRRS.  So, the MPS only needs to be configured
+                        * for the upstream communication.  This being the case,
+                        * walk from the top down and set the MPS of the child
+                        * to that of the parent bus.
+                        */
+                       mps = 128 << dev->bus->self->pcie_mpss;
+                       if (mps > dev_mpss)
+                               dev_warn(&dev->dev, "MPS configured higher than"
+                                        " maximum supported by the device.  If"
+                                        " a bus issue occurs, try running with"
+                                        " pci=pcie_bus_safe.\n");
+               }
+
+               dev->pcie_mpss = ffs(mps) - 8;
+       }
+
+       rc = pcie_set_mps(dev, mps);
+       if (rc)
+               dev_err(&dev->dev, "Failed attempting to set the MPS\n");
+}
+
+static void pcie_write_mrrs(struct pci_dev *dev, int mps)
+{
+       int rc, mrrs, dev_mpss;
+
+       /* In the "safe" case, do not configure the MRRS.  There appear to be
+        * issues with setting MRRS to 0 on a number of devices.
+        */
+
+       if (pcie_bus_config != PCIE_BUS_PERFORMANCE)
+               return;
+
+       dev_mpss = 128 << dev->pcie_mpss;
+
+       /* For Max performance, the MRRS must be set to the largest supported
+        * value.  However, it cannot be configured larger than the MPS the
+        * device or the bus can support.  This assumes that the largest MRRS
+        * available on the device cannot be smaller than the device MPSS.
+        */
+       mrrs = min(mps, dev_mpss);
+
+       /* MRRS is a R/W register.  Invalid values can be written, but a
+        * subsequent read will verify if the value is acceptable or not.
+        * If the MRRS value provided is not acceptable (e.g., too large),
+        * shrink the value until it is acceptable to the HW.
+        */
+       while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {
+               dev_warn(&dev->dev, "Attempting to modify the PCI-E MRRS value"
+                        " to %d.  If any issues are encountered, please try "
+                        "running with pci=pcie_bus_safe\n", mrrs);
+               rc = pcie_set_readrq(dev, mrrs);
+               if (rc)
+                       dev_err(&dev->dev,
+                               "Failed attempting to set the MRRS\n");
+
+               mrrs /= 2;
+       }
+}
+
+static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
+{
+       int mps = 128 << *(u8 *)data;
+
+       if (!pci_is_pcie(dev))
+               return 0;
+
+       dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
+                pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
+
+       pcie_write_mps(dev, mps);
+       pcie_write_mrrs(dev, mps);
+
+       dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
+                pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
+
+       return 0;
+}
+
+/* pcie_bus_configure_mps requires that pci_walk_bus work in a top-down,
+ * parents then children fashion.  If this changes, then this code will not
+ * work as designed.
+ */
+void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
+{
+       u8 smpss = mpss;
+
+       if (!pci_is_pcie(bus->self))
+               return;
+
+       if (pcie_bus_config == PCIE_BUS_SAFE) {
+               pcie_find_smpss(bus->self, &smpss);
+               pci_walk_bus(bus, pcie_find_smpss, &smpss);
+       }
+
+       pcie_bus_configure_set(bus->self, &smpss);
+       pci_walk_bus(bus, pcie_bus_configure_set, &smpss);
+}
+EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
+
 unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
 {
        unsigned int devfn, pass, max = bus->secondary;
index 8a1d3c7..784da9d 100644 (file)
@@ -34,6 +34,7 @@ struct resource_list_x {
        resource_size_t start;
        resource_size_t end;
        resource_size_t add_size;
+       resource_size_t min_align;
        unsigned long flags;
 };
 
@@ -65,7 +66,7 @@ void pci_realloc(void)
  */
 static void add_to_list(struct resource_list_x *head,
                 struct pci_dev *dev, struct resource *res,
-                resource_size_t add_size)
+                resource_size_t add_size, resource_size_t min_align)
 {
        struct resource_list_x *list = head;
        struct resource_list_x *ln = list->next;
@@ -84,13 +85,16 @@ static void add_to_list(struct resource_list_x *head,
        tmp->end = res->end;
        tmp->flags = res->flags;
        tmp->add_size = add_size;
+       tmp->min_align = min_align;
        list->next = tmp;
 }
 
 static void add_to_failed_list(struct resource_list_x *head,
                                struct pci_dev *dev, struct resource *res)
 {
-       add_to_list(head, dev, res, 0);
+       add_to_list(head, dev, res,
+                       0 /* dont care */,
+                       0 /* dont care */);
 }
 
 static void __dev_sort_resources(struct pci_dev *dev,
@@ -121,18 +125,18 @@ static inline void reset_resource(struct resource *res)
 }
 
 /**
- * adjust_resources_sorted() - satisfy any additional resource requests
+ * reassign_resources_sorted() - satisfy any additional resource requests
  *
- * @add_head : head of the list tracking requests requiring additional
+ * @realloc_head : head of the list tracking requests requiring additional
  *             resources
  * @head     : head of the list tracking requests with allocated
  *             resources
  *
- * Walk through each element of the add_head and try to procure
+ * Walk through each element of the realloc_head and try to procure
  * additional resources for the element, provided the element
  * is in the head list.
  */
-static void adjust_resources_sorted(struct resource_list_x *add_head,
+static void reassign_resources_sorted(struct resource_list_x *realloc_head,
                struct resource_list *head)
 {
        struct resource *res;
@@ -141,8 +145,8 @@ static void adjust_resources_sorted(struct resource_list_x *add_head,
        resource_size_t add_size;
        int idx;
 
-       prev = add_head;
-       for (list = add_head->next; list;) {
+       prev = realloc_head;
+       for (list = realloc_head->next; list;) {
                res = list->res;
                /* skip resource that has been reset */
                if (!res->flags)
@@ -159,13 +163,17 @@ static void adjust_resources_sorted(struct resource_list_x *add_head,
 
                idx = res - &list->dev->resource[0];
                add_size=list->add_size;
-               if (!resource_size(res) && add_size) {
-                        res->end = res->start + add_size - 1;
-                        if(pci_assign_resource(list->dev, idx))
+               if (!resource_size(res)) {
+                       res->start = list->start;
+                       res->end = res->start + add_size - 1;
+                       if(pci_assign_resource(list->dev, idx))
                                reset_resource(res);
-               } else if (add_size) {
-                       adjust_resource(res, res->start,
-                               resource_size(res) + add_size);
+               } else {
+                       resource_size_t align = list->min_align;
+                       res->flags |= list->flags & (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
+                       if (pci_reassign_resource(list->dev, idx, add_size, align))
+                               dev_printk(KERN_DEBUG, &list->dev->dev, "failed to add optional resources res=%pR\n",
+                                                       res);
                }
 out:
                tmp = list;
@@ -210,16 +218,16 @@ static void assign_requested_resources_sorted(struct resource_list *head,
 }
 
 static void __assign_resources_sorted(struct resource_list *head,
-                                struct resource_list_x *add_head,
+                                struct resource_list_x *realloc_head,
                                 struct resource_list_x *fail_head)
 {
        /* Satisfy the must-have resource requests */
        assign_requested_resources_sorted(head, fail_head);
 
-       /* Try to satisfy any additional nice-to-have resource
+       /* Try to satisfy any additional optional resource
                requests */
-       if (add_head)
-               adjust_resources_sorted(add_head, head);
+       if (realloc_head)
+               reassign_resources_sorted(realloc_head, head);
        free_list(resource_list, head);
 }
 
@@ -235,7 +243,7 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev,
 }
 
 static void pbus_assign_resources_sorted(const struct pci_bus *bus,
-                                        struct resource_list_x *add_head,
+                                        struct resource_list_x *realloc_head,
                                         struct resource_list_x *fail_head)
 {
        struct pci_dev *dev;
@@ -245,7 +253,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
        list_for_each_entry(dev, &bus->devices, bus_list)
                __dev_sort_resources(dev, &head);
 
-       __assign_resources_sorted(&head, add_head, fail_head);
+       __assign_resources_sorted(&head, realloc_head, fail_head);
 }
 
 void pci_setup_cardbus(struct pci_bus *bus)
@@ -540,13 +548,27 @@ static resource_size_t calculate_memsize(resource_size_t size,
        return size;
 }
 
+static resource_size_t get_res_add_size(struct resource_list_x *realloc_head,
+                                       struct resource *res)
+{
+       struct resource_list_x *list;
+
+       /* check if it is in realloc_head list */
+       for (list = realloc_head->next; list && list->res != res;
+                       list = list->next);
+       if (list)
+               return list->add_size;
+
+       return 0;
+}
+
 /**
  * pbus_size_io() - size the io window of a given bus
  *
  * @bus : the bus
  * @min_size : the minimum io window that must to be allocated
  * @add_size : additional optional io window
- * @add_head : track the additional io window on this list
+ * @realloc_head : track the additional io window on this list
  *
  * Sizing the IO windows of the PCI-PCI bridge is trivial,
  * since these windows have 4K granularity and the IO ranges
@@ -554,11 +576,12 @@ static resource_size_t calculate_memsize(resource_size_t size,
  * We must be careful with the ISA aliasing though.
  */
 static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
-               resource_size_t add_size, struct resource_list_x *add_head)
+               resource_size_t add_size, struct resource_list_x *realloc_head)
 {
        struct pci_dev *dev;
        struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
        unsigned long size = 0, size0 = 0, size1 = 0;
+       resource_size_t children_add_size = 0;
 
        if (!b_res)
                return;
@@ -579,11 +602,16 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
                                size += r_size;
                        else
                                size1 += r_size;
+
+                       if (realloc_head)
+                               children_add_size += get_res_add_size(realloc_head, r);
                }
        }
        size0 = calculate_iosize(size, min_size, size1,
                        resource_size(b_res), 4096);
-       size1 = (!add_head || (add_head && !add_size)) ? size0 :
+       if (children_add_size > add_size)
+               add_size = children_add_size;
+       size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
                calculate_iosize(size, min_size+add_size, size1,
                        resource_size(b_res), 4096);
        if (!size0 && !size1) {
@@ -598,8 +626,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
        b_res->start = 4096;
        b_res->end = b_res->start + size0 - 1;
        b_res->flags |= IORESOURCE_STARTALIGN;
-       if (size1 > size0 && add_head)
-               add_to_list(add_head, bus->self, b_res, size1-size0);
+       if (size1 > size0 && realloc_head)
+               add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
 }
 
 /**
@@ -608,7 +636,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
  * @bus : the bus
  * @min_size : the minimum memory window that must to be allocated
  * @add_size : additional optional memory window
- * @add_head : track the additional memory window on this list
+ * @realloc_head : track the additional memory window on this list
  *
  * Calculate the size of the bus and minimal alignment which
  * guarantees that all child resources fit in this size.
@@ -616,7 +644,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                         unsigned long type, resource_size_t min_size,
                        resource_size_t add_size,
-                       struct resource_list_x *add_head)
+                       struct resource_list_x *realloc_head)
 {
        struct pci_dev *dev;
        resource_size_t min_align, align, size, size0, size1;
@@ -624,6 +652,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        int order, max_order;
        struct resource *b_res = find_free_bus_resource(bus, type);
        unsigned int mem64_mask = 0;
+       resource_size_t children_add_size = 0;
 
        if (!b_res)
                return 0;
@@ -645,6 +674,16 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                        if (r->parent || (r->flags & mask) != type)
                                continue;
                        r_size = resource_size(r);
+#ifdef CONFIG_PCI_IOV
+                       /* put SRIOV requested res to the optional list */
+                       if (realloc_head && i >= PCI_IOV_RESOURCES &&
+                                       i <= PCI_IOV_RESOURCE_END) {
+                               r->end = r->start - 1;
+                               add_to_list(realloc_head, dev, r, r_size, 0/* dont' care */);
+                               children_add_size += r_size;
+                               continue;
+                       }
+#endif
                        /* For bridges size != alignment */
                        align = pci_resource_alignment(dev, r);
                        order = __ffs(align) - 20;
@@ -665,6 +704,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                        if (order > max_order)
                                max_order = order;
                        mem64_mask &= r->flags & IORESOURCE_MEM_64;
+
+                       if (realloc_head)
+                               children_add_size += get_res_add_size(realloc_head, r);
                }
        }
        align = 0;
@@ -681,7 +723,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                align += aligns[order];
        }
        size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
-       size1 = (!add_head || (add_head && !add_size)) ? size0 :
+       if (children_add_size > add_size)
+               add_size = children_add_size;
+       size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
                calculate_memsize(size, min_size+add_size, 0,
                                resource_size(b_res), min_align);
        if (!size0 && !size1) {
@@ -695,12 +739,22 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        b_res->start = min_align;
        b_res->end = size0 + min_align - 1;
        b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
-       if (size1 > size0 && add_head)
-               add_to_list(add_head, bus->self, b_res, size1-size0);
+       if (size1 > size0 && realloc_head)
+               add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
        return 1;
 }
 
-static void pci_bus_size_cardbus(struct pci_bus *bus)
+unsigned long pci_cardbus_resource_alignment(struct resource *res)
+{
+       if (res->flags & IORESOURCE_IO)
+               return pci_cardbus_io_size;
+       if (res->flags & IORESOURCE_MEM)
+               return pci_cardbus_mem_size;
+       return 0;
+}
+
+static void pci_bus_size_cardbus(struct pci_bus *bus,
+                       struct resource_list_x *realloc_head)
 {
        struct pci_dev *bridge = bus->self;
        struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
@@ -711,12 +765,14 @@ static void pci_bus_size_cardbus(struct pci_bus *bus)
         * a fixed amount of bus space for CardBus bridges.
         */
        b_res[0].start = 0;
-       b_res[0].end = pci_cardbus_io_size - 1;
        b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
+       if (realloc_head)
+               add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size, 0 /* dont care */);
 
        b_res[1].start = 0;
-       b_res[1].end = pci_cardbus_io_size - 1;
        b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
+       if (realloc_head)
+               add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size, 0 /* dont care */);
 
        /*
         * Check whether prefetchable memory is supported
@@ -736,21 +792,31 @@ static void pci_bus_size_cardbus(struct pci_bus *bus)
         */
        if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
                b_res[2].start = 0;
-               b_res[2].end = pci_cardbus_mem_size - 1;
                b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN;
+               if (realloc_head)
+                       add_to_list(realloc_head, bridge, b_res+2, pci_cardbus_mem_size, 0 /* dont care */);
 
                b_res[3].start = 0;
-               b_res[3].end = pci_cardbus_mem_size - 1;
                b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
+               if (realloc_head)
+                       add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size, 0 /* dont care */);
        } else {
                b_res[3].start = 0;
-               b_res[3].end = pci_cardbus_mem_size * 2 - 1;
                b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
+               if (realloc_head)
+                       add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size * 2, 0 /* dont care */);
        }
+
+       /* set the size of the resource to zero, so that the resource does not
+        * get assigned during required-resource allocation cycle but gets assigned
+        * during the optional-resource allocation cycle.
+        */
+       b_res[0].start = b_res[1].start = b_res[2].start = b_res[3].start = 1;
+       b_res[0].end = b_res[1].end = b_res[2].end = b_res[3].end = 0;
 }
 
 void __ref __pci_bus_size_bridges(struct pci_bus *bus,
-                       struct resource_list_x *add_head)
+                       struct resource_list_x *realloc_head)
 {
        struct pci_dev *dev;
        unsigned long mask, prefmask;
@@ -763,12 +829,12 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
 
                switch (dev->class >> 8) {
                case PCI_CLASS_BRIDGE_CARDBUS:
-                       pci_bus_size_cardbus(b);
+                       pci_bus_size_cardbus(b, realloc_head);
                        break;
 
                case PCI_CLASS_BRIDGE_PCI:
                default:
-                       __pci_bus_size_bridges(b, add_head);
+                       __pci_bus_size_bridges(b, realloc_head);
                        break;
                }
        }
@@ -792,7 +858,7 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
                 * Follow thru
                 */
        default:
-               pbus_size_io(bus, 0, additional_io_size, add_head);
+               pbus_size_io(bus, 0, additional_io_size, realloc_head);
                /* If the bridge supports prefetchable range, size it
                   separately. If it doesn't, or its prefetchable window
                   has already been allocated by arch code, try
@@ -800,11 +866,11 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
                   resources. */
                mask = IORESOURCE_MEM;
                prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-               if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head))
+               if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, realloc_head))
                        mask = prefmask; /* Success, size non-prefetch only. */
                else
                        additional_mem_size += additional_mem_size;
-               pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head);
+               pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, realloc_head);
                break;
        }
 }
@@ -816,20 +882,20 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
 EXPORT_SYMBOL(pci_bus_size_bridges);
 
 static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
-                                        struct resource_list_x *add_head,
+                                        struct resource_list_x *realloc_head,
                                         struct resource_list_x *fail_head)
 {
        struct pci_bus *b;
        struct pci_dev *dev;
 
-       pbus_assign_resources_sorted(bus, add_head, fail_head);
+       pbus_assign_resources_sorted(bus, realloc_head, fail_head);
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                b = dev->subordinate;
                if (!b)
                        continue;
 
-               __pci_bus_assign_resources(b, add_head, fail_head);
+               __pci_bus_assign_resources(b, realloc_head, fail_head);
 
                switch (dev->class >> 8) {
                case PCI_CLASS_BRIDGE_PCI:
@@ -1039,7 +1105,7 @@ void __init
 pci_assign_unassigned_resources(void)
 {
        struct pci_bus *bus;
-       struct resource_list_x add_list; /* list of resources that
+       struct resource_list_x realloc_list; /* list of resources that
                                        want additional resources */
        int tried_times = 0;
        enum release_type rel_type = leaf_only;
@@ -1052,7 +1118,7 @@ pci_assign_unassigned_resources(void)
 
 
        head.next = NULL;
-       add_list.next = NULL;
+       realloc_list.next = NULL;
 
        pci_try_num = max_depth + 1;
        printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
@@ -1062,12 +1128,12 @@ again:
        /* Depth first, calculate sizes and alignments of all
           subordinate buses. */
        list_for_each_entry(bus, &pci_root_buses, node)
-               __pci_bus_size_bridges(bus, &add_list);
+               __pci_bus_size_bridges(bus, &realloc_list);
 
        /* Depth last, allocate resources and update the hardware. */
        list_for_each_entry(bus, &pci_root_buses, node)
-               __pci_bus_assign_resources(bus, &add_list, &head);
-       BUG_ON(add_list.next);
+               __pci_bus_assign_resources(bus, &realloc_list, &head);
+       BUG_ON(realloc_list.next);
        tried_times++;
 
        /* any device complain? */
index 319f359..51a9095 100644 (file)
@@ -128,16 +128,16 @@ void pci_disable_bridge_window(struct pci_dev *dev)
 }
 #endif /* CONFIG_PCI_QUIRKS */
 
+
+
 static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
-                                int resno)
+               int resno, resource_size_t size, resource_size_t align)
 {
        struct resource *res = dev->resource + resno;
-       resource_size_t size, min, align;
+       resource_size_t min;
        int ret;
 
-       size = resource_size(res);
        min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
-       align = pci_resource_alignment(dev, res);
 
        /* First, try exact prefetching match.. */
        ret = pci_bus_alloc_resource(bus, res, size, align, min,
@@ -154,56 +154,101 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
                ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
                                             pcibios_align_resource, dev);
        }
+       return ret;
+}
 
-       if (ret < 0 && dev->fw_addr[resno]) {
-               struct resource *root, *conflict;
-               resource_size_t start, end;
+static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, 
+               int resno, resource_size_t size)
+{
+       struct resource *root, *conflict;
+       resource_size_t start, end;
+       int ret = 0;
 
-               /*
-                * If we failed to assign anything, let's try the address
-                * where firmware left it.  That at least has a chance of
-                * working, which is better than just leaving it disabled.
-                */
+       if (res->flags & IORESOURCE_IO)
+               root = &ioport_resource;
+       else
+               root = &iomem_resource;
+
+       start = res->start;
+       end = res->end;
+       res->start = dev->fw_addr[resno];
+       res->end = res->start + size - 1;
+       dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
+                resno, res);
+       conflict = request_resource_conflict(root, res);
+       if (conflict) {
+               dev_info(&dev->dev,
+                        "BAR %d: %pR conflicts with %s %pR\n", resno,
+                        res, conflict->name, conflict);
+               res->start = start;
+               res->end = end;
+               ret = 1;
+       }
+       return ret;
+}
+
+static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align)
+{
+       struct resource *res = dev->resource + resno;
+       struct pci_bus *bus;
+       int ret;
+       char *type;
 
-               if (res->flags & IORESOURCE_IO)
-                       root = &ioport_resource;
+       bus = dev->bus;
+       while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
+               if (!bus->parent || !bus->self->transparent)
+                       break;
+               bus = bus->parent;
+       }
+
+       if (ret) {
+               if (res->flags & IORESOURCE_MEM)
+                       if (res->flags & IORESOURCE_PREFETCH)
+                               type = "mem pref";
+                       else
+                               type = "mem";
+               else if (res->flags & IORESOURCE_IO)
+                       type = "io";
                else
-                       root = &iomem_resource;
-
-               start = res->start;
-               end = res->end;
-               res->start = dev->fw_addr[resno];
-               res->end = res->start + size - 1;
-               dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
-                        resno, res);
-               conflict = request_resource_conflict(root, res);
-               if (conflict) {
-                       dev_info(&dev->dev,
-                                "BAR %d: %pR conflicts with %s %pR\n", resno,
-                                res, conflict->name, conflict);
-                       res->start = start;
-                       res->end = end;
-               } else
-                       ret = 0;
+                       type = "unknown";
+               dev_info(&dev->dev,
+                        "BAR %d: can't assign %s (size %#llx)\n",
+                        resno, type, (unsigned long long) resource_size(res));
        }
 
+       return ret;
+}
+
+int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
+                       resource_size_t min_align)
+{
+       struct resource *res = dev->resource + resno;
+       resource_size_t new_size;
+       int ret;
+
+       if (!res->parent) {
+               dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resouce %pR "
+                        "\n", resno, res);
+               return -EINVAL;
+       }
+
+       new_size = resource_size(res) + addsize + min_align;
+       ret = _pci_assign_resource(dev, resno, new_size, min_align);
        if (!ret) {
                res->flags &= ~IORESOURCE_STARTALIGN;
                dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
                if (resno < PCI_BRIDGE_RESOURCES)
                        pci_update_resource(dev, resno);
        }
-
        return ret;
 }
 
 int pci_assign_resource(struct pci_dev *dev, int resno)
 {
        struct resource *res = dev->resource + resno;
-       resource_size_t align;
+       resource_size_t align, size;
        struct pci_bus *bus;
        int ret;
-       char *type;
 
        align = pci_resource_alignment(dev, res);
        if (!align) {
@@ -213,34 +258,27 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        }
 
        bus = dev->bus;
-       while ((ret = __pci_assign_resource(bus, dev, resno))) {
-               if (bus->parent && bus->self->transparent)
-                       bus = bus->parent;
-               else
-                       bus = NULL;
-               if (bus)
-                       continue;
-               break;
-       }
+       size = resource_size(res);
+       ret = _pci_assign_resource(dev, resno, size, align);
 
-       if (ret) {
-               if (res->flags & IORESOURCE_MEM)
-                       if (res->flags & IORESOURCE_PREFETCH)
-                               type = "mem pref";
-                       else
-                               type = "mem";
-               else if (res->flags & IORESOURCE_IO)
-                       type = "io";
-               else
-                       type = "unknown";
-               dev_info(&dev->dev,
-                        "BAR %d: can't assign %s (size %#llx)\n",
-                        resno, type, (unsigned long long) resource_size(res));
-       }
+       /*
+        * If we failed to assign anything, let's try the address
+        * where firmware left it.  That at least has a chance of
+        * working, which is better than just leaving it disabled.
+        */
+       if (ret < 0 && dev->fw_addr[resno])
+               ret = pci_revert_fw_address(res, dev, resno, size);
 
+       if (!ret) {
+               res->flags &= ~IORESOURCE_STARTALIGN;
+               dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
+               if (resno < PCI_BRIDGE_RESOURCES)
+                       pci_update_resource(dev, resno);
+       }
        return ret;
 }
 
+
 /* Sort resources by alignment */
 void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
 {
index 7106b49..ffc5033 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
index cc21fa2..ef8efad 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
index a675e31..d32d0d7 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/s3c_adc_battery.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <plat/adc.h>
 
index ee89358..ebe77dd 100644 (file)
@@ -505,8 +505,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
        rdev->dev.dma_mask = &rdev->dma_mask;
        rdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if ((rdev->pef & RIO_PEF_INB_DOORBELL) &&
-           (rdev->dst_ops & RIO_DST_OPS_DOORBELL))
+       if (rdev->dst_ops & RIO_DST_OPS_DOORBELL)
                rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE],
                                   0, 0xffff);
 
index 3195dbd..44e91e5 100644 (file)
@@ -639,7 +639,7 @@ EXPORT_SYMBOL_GPL(rtc_irq_unregister);
 static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
 {
        /*
-        * We unconditionally cancel the timer here, because otherwise
+        * We always cancel the timer here first, because otherwise
         * we could run into BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
         * when we manage to start the timer before the callback
         * returns HRTIMER_RESTART.
@@ -708,7 +708,7 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
        int err = 0;
        unsigned long flags;
 
-       if (freq <= 0 || freq > 5000)
+       if (freq <= 0 || freq > RTC_MAX_FREQ)
                return -EINVAL;
 retry:
        spin_lock_irqsave(&rtc->irq_task_lock, flags);
index 335551d..14a42a1 100644 (file)
@@ -36,6 +36,7 @@
  */
 struct ep93xx_rtc {
        void __iomem    *mmio_base;
+       struct rtc_device *rtc;
 };
 
 static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
@@ -130,7 +131,6 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
 {
        struct ep93xx_rtc *ep93xx_rtc;
        struct resource *res;
-       struct rtc_device *rtc;
        int err;
 
        ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL);
@@ -151,12 +151,12 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
                return -ENXIO;
 
        pdev->dev.platform_data = ep93xx_rtc;
-       platform_set_drvdata(pdev, rtc);
+       platform_set_drvdata(pdev, ep93xx_rtc);
 
-       rtc = rtc_device_register(pdev->name,
+       ep93xx_rtc->rtc = rtc_device_register(pdev->name,
                                &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc)) {
-               err = PTR_ERR(rtc);
+       if (IS_ERR(ep93xx_rtc->rtc)) {
+               err = PTR_ERR(ep93xx_rtc->rtc);
                goto exit;
        }
 
@@ -167,7 +167,7 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
        return 0;
 
 fail:
-       rtc_device_unregister(rtc);
+       rtc_device_unregister(ep93xx_rtc->rtc);
 exit:
        platform_set_drvdata(pdev, NULL);
        pdev->dev.platform_data = NULL;
@@ -176,11 +176,11 @@ exit:
 
 static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
 {
-       struct rtc_device *rtc = platform_get_drvdata(pdev);
+       struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev);
 
        sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
        platform_set_drvdata(pdev, NULL);
-       rtc_device_unregister(rtc);
+       rtc_device_unregister(ep93xx_rtc->rtc);
        pdev->dev.platform_data = NULL;
 
        return 0;
index 075f170..c4cf057 100644 (file)
@@ -85,6 +85,8 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
        time -= tm->tm_hour * 3600;
        tm->tm_min = time / 60;
        tm->tm_sec = time - tm->tm_min * 60;
+
+       tm->tm_isdst = 0;
 }
 EXPORT_SYMBOL(rtc_time_to_tm);
 
index 9329dbb..4e7c04e 100644 (file)
@@ -152,10 +152,6 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
                goto retry_get_time;
        }
 
-       pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
-                1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
-                rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
-
        rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
        rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
        rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
@@ -164,6 +160,11 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
        rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
 
        rtc_tm->tm_year += 100;
+
+       pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
+                1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
+                rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
+
        rtc_tm->tm_mon -= 1;
 
        clk_disable(rtc_clk);
@@ -269,10 +270,9 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        clk_enable(rtc_clk);
        pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
                 alrm->enabled,
-                1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+                1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
                 tm->tm_hour, tm->tm_min, tm->tm_sec);
 
-
        alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
        writeb(0x00, base + S3C2410_RTCALM);
 
@@ -319,49 +319,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
        return 0;
 }
 
-static int s3c_rtc_open(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
-       int ret;
-
-       ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
-                         IRQF_DISABLED,  "s3c2410-rtc alarm", rtc_dev);
-
-       if (ret) {
-               dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
-               return ret;
-       }
-
-       ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
-                         IRQF_DISABLED,  "s3c2410-rtc tick", rtc_dev);
-
-       if (ret) {
-               dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
-               goto tick_err;
-       }
-
-       return ret;
-
- tick_err:
-       free_irq(s3c_rtc_alarmno, rtc_dev);
-       return ret;
-}
-
-static void s3c_rtc_release(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
-
-       /* do not clear AIE here, it may be needed for wake */
-
-       free_irq(s3c_rtc_alarmno, rtc_dev);
-       free_irq(s3c_rtc_tickno, rtc_dev);
-}
-
 static const struct rtc_class_ops s3c_rtcops = {
-       .open           = s3c_rtc_open,
-       .release        = s3c_rtc_release,
        .read_time      = s3c_rtc_gettime,
        .set_time       = s3c_rtc_settime,
        .read_alarm     = s3c_rtc_getalarm,
@@ -425,6 +383,9 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
+       free_irq(s3c_rtc_alarmno, rtc);
+       free_irq(s3c_rtc_tickno, rtc);
+
        platform_set_drvdata(dev, NULL);
        rtc_device_unregister(rtc);
 
@@ -548,10 +509,32 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 
        s3c_rtc_setfreq(&pdev->dev, 1);
 
+       ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
+                         IRQF_DISABLED,  "s3c2410-rtc alarm", rtc);
+       if (ret) {
+               dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
+               goto err_alarm_irq;
+       }
+
+       ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
+                         IRQF_DISABLED,  "s3c2410-rtc tick", rtc);
+       if (ret) {
+               dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
+               free_irq(s3c_rtc_alarmno, rtc);
+               goto err_tick_irq;
+       }
+
        clk_disable(rtc_clk);
 
        return 0;
 
+ err_tick_irq:
+       free_irq(s3c_rtc_alarmno, rtc);
+
+ err_alarm_irq:
+       platform_set_drvdata(pdev, NULL);
+       rtc_device_unregister(rtc);
+
  err_nortc:
        s3c_rtc_enable(pdev, 0);
        clk_disable(rtc_clk);
index 9a81f77..20687d5 100644 (file)
@@ -362,14 +362,6 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
        int res;
        u8 rd_reg;
 
-#ifdef CONFIG_LOCKDEP
-       /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
-        * we don't want and can't tolerate.  Although it might be
-        * friendlier not to borrow this thread context...
-        */
-       local_irq_enable();
-#endif
-
        res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
        if (res)
                goto out;
@@ -428,24 +420,12 @@ static struct rtc_class_ops twl_rtc_ops = {
 static int __devinit twl_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
-       int ret = 0;
+       int ret = -EINVAL;
        int irq = platform_get_irq(pdev, 0);
        u8 rd_reg;
 
        if (irq <= 0)
-               return -EINVAL;
-
-       rtc = rtc_device_register(pdev->name,
-                                 &pdev->dev, &twl_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc)) {
-               ret = PTR_ERR(rtc);
-               dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
-                       PTR_ERR(rtc));
-               goto out0;
-
-       }
-
-       platform_set_drvdata(pdev, rtc);
+               goto out1;
 
        ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
        if (ret < 0)
@@ -462,14 +442,6 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
        if (ret < 0)
                goto out1;
 
-       ret = request_irq(irq, twl_rtc_interrupt,
-                               IRQF_TRIGGER_RISING,
-                               dev_name(&rtc->dev), rtc);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "IRQ is not free.\n");
-               goto out1;
-       }
-
        if (twl_class_is_6030()) {
                twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK,
                        REG_INT_MSK_LINE_A);
@@ -480,28 +452,44 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
        /* Check RTC module status, Enable if it is off */
        ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
        if (ret < 0)
-               goto out2;
+               goto out1;
 
        if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) {
                dev_info(&pdev->dev, "Enabling TWL-RTC.\n");
                rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M;
                ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
                if (ret < 0)
-                       goto out2;
+                       goto out1;
        }
 
        /* init cached IRQ enable bits */
        ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
        if (ret < 0)
+               goto out1;
+
+       rtc = rtc_device_register(pdev->name,
+                                 &pdev->dev, &twl_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc);
+               dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
+                       PTR_ERR(rtc));
+               goto out1;
+       }
+
+       ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt,
+                                  IRQF_TRIGGER_RISING,
+                                  dev_name(&rtc->dev), rtc);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "IRQ is not free.\n");
                goto out2;
+       }
 
-       return ret;
+       platform_set_drvdata(pdev, rtc);
+       return 0;
 
 out2:
-       free_irq(irq, rtc);
-out1:
        rtc_device_unregister(rtc);
-out0:
+out1:
        return ret;
 }
 
index eb4e034..f1a2016 100644 (file)
@@ -249,6 +249,7 @@ static int dasd_ioctl_reset_profile(struct dasd_block *block)
 static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
 {
        struct dasd_profile_info_t *data;
+       int rc = 0;
 
        data = kmalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
@@ -279,11 +280,14 @@ static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
                spin_unlock_bh(&block->profile.lock);
        } else {
                spin_unlock_bh(&block->profile.lock);
-               return -EIO;
+               rc = -EIO;
+               goto out;
        }
        if (copy_to_user(argp, data, sizeof(*data)))
-               return -EFAULT;
-       return 0;
+               rc = -EFAULT;
+out:
+       kfree(data);
+       return rc;
 }
 #else
 static int dasd_ioctl_reset_profile(struct dasd_block *block)
index be55fb2..837e010 100644 (file)
@@ -383,8 +383,10 @@ static int sclp_attach_storage(u8 id)
        switch (sccb->header.response_code) {
        case 0x0020:
                set_bit(id, sclp_storage_ids);
-               for (i = 0; i < sccb->assigned; i++)
-                       sclp_unassign_storage(sccb->entries[i] >> 16);
+               for (i = 0; i < sccb->assigned; i++) {
+                       if (sccb->entries[i])
+                               sclp_unassign_storage(sccb->entries[i] >> 16);
+               }
                break;
        default:
                rc = -EIO;
index 2c33ce6..0f5599e 100644 (file)
@@ -1,6 +1,6 @@
 config SCSI_QLA_ISCSI
        tristate "QLogic ISP4XXX and ISP82XX host adapter family support"
-       depends on PCI && SCSI
+       depends on PCI && SCSI && NET
        select SCSI_ISCSI_ATTRS
        ---help---
        This driver supports the QLogic 40xx (ISP4XXX) and 8022 (ISP82XX)
index f33e2dd..33b2ed4 100644 (file)
@@ -186,6 +186,9 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
     !defined(CONFIG_CPU_SUBTYPE_SH7709)
        [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
 #endif
+#if defined(CONFIG_ARCH_SH7372)
+       [IRQ_TYPE_EDGE_BOTH] = VALID(4),
+#endif
 };
 
 static int intc_set_type(struct irq_data *data, unsigned int type)
index 34253cf..4a70180 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/io.h>
 #include <linux/errno.h>
+#include <linux/string.h>
 
 #include <brcm_hw_ids.h>
 #include <chipcommon.h>
index bbf2189..823b5e4 100644 (file)
@@ -18,6 +18,7 @@
 #define _BRCM_TYPES_H_
 
 #include <linux/types.h>
+#include <linux/io.h>
 
 /* Bus types */
 #define        SI_BUS                  0       /* SOC Interconnect */
index 02e17c9..fd211f3 100644 (file)
@@ -711,10 +711,11 @@ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
        /* Create drm encoder object */
        connector = &dsi_connector->base.base;
        encoder = &dbi_output->base.base;
+       /* Review this if we ever get MIPI-HDMI bridges or similar */
        drm_encoder_init(dev,
                        encoder,
                        p_funcs->encoder_funcs,
-                       DRM_MODE_ENCODER_MIPI);
+                       DRM_MODE_ENCODER_LVDS);
        drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);
 
        /* Attach to given connector */
index dc6242c..f0fa986 100644 (file)
@@ -42,9 +42,6 @@
 #include "mdfld_dsi_output.h"
 #include "mdfld_output.h"
 
-#define DRM_MODE_ENCODER_MIPI  5
-
-
 /*
  * DBI encoder which inherits from mdfld_dsi_encoder
  */
index 6e03a91..e685f12 100644 (file)
@@ -777,10 +777,15 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
        /* Create drm encoder object */
        connector = &dsi_connector->base.base;
        encoder = &dpi_output->base.base;
+       /*
+        * On existing hardware this will be a panel of some form,
+        * if future devices also have HDMI bridges this will need
+        * revisiting
+        */
        drm_encoder_init(dev,
                        encoder,
                        p_funcs->encoder_funcs,
-                       DRM_MODE_ENCODER_MIPI);
+                       DRM_MODE_ENCODER_LVDS);
        drm_encoder_helper_add(encoder,
                                p_funcs->encoder_helper_funcs);
        
index 7536095..9050c0f 100644 (file)
@@ -955,7 +955,9 @@ void mdfld_dsi_output_init(struct drm_device *dev,
        psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
 
        connector = &psb_output->base;
-       drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, DRM_MODE_CONNECTOR_MIPI);
+       /* Revisit type if MIPI/HDMI bridges ever appear on Medfield */
+       drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
+                                               DRM_MODE_CONNECTOR_LVDS);
        drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
        
        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
index 38165e8..09e9687 100644 (file)
@@ -21,8 +21,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#define DRM_MODE_ENCODER_MIPI  5
-
 /* Medfield DSI controller registers */
 
 #define MIPIA_DEVICE_READY_REG                         0xb000
index 72f487a..fd4732d 100644 (file)
@@ -35,7 +35,6 @@
 
 /* Append new drm mode definition here, align with libdrm definition */
 #define DRM_MODE_SCALE_NO_SCALE        2
-#define DRM_MODE_CONNECTOR_MIPI         15
 
 enum {
        CHIP_PSB_8108 = 0,              /* Poulsbo */
index 9c0d293..c3d73f8 100644 (file)
@@ -26,6 +26,7 @@
 **********************************************************************/
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/interrupt.h>
 #include <linux/phy.h>
 #include <linux/ratelimit.h>
 #include <net/dst.h>
index 9708254..d0e2d51 100644 (file)
@@ -26,6 +26,7 @@
 **********************************************************************/
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/interrupt.h>
 #include <net/dst.h>
 
 #include <asm/octeon/octeon.h>
index 589a055..3d1279c 100644 (file)
@@ -209,7 +209,6 @@ int dsp_clk_enable(enum dsp_clk_id clk_id)
                break;
 #ifdef CONFIG_OMAP_MCBSP
        case MCBSP_CLK:
-               omap_mcbsp_set_io_type(MCBSP_ID(clk_id), OMAP_MCBSP_POLL_IO);
                omap_mcbsp_request(MCBSP_ID(clk_id));
                omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PAD_SRC);
                break;
index 975e34b..1ca66ea 100644 (file)
@@ -604,7 +604,7 @@ int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
        struct tmem_obj *obj;
        void *pampd;
        bool ephemeral = is_ephemeral(pool);
-       uint32_t ret = -1;
+       int ret = -1;
        struct tmem_hashbucket *hb;
        bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral);
        bool lock_held = false;
index 855a5bb..a3f5162 100644 (file)
@@ -1158,7 +1158,7 @@ static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph,
        size_t clen;
        int ret;
        unsigned long count;
-       struct page *page = virt_to_page(data);
+       struct page *page = (struct page *)(data);
        struct zcache_client *cli = pool->client;
        uint16_t client_id = get_client_id_from_client(cli);
        unsigned long zv_mean_zsize;
@@ -1227,7 +1227,7 @@ static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw,
        int ret = 0;
 
        BUG_ON(is_ephemeral(pool));
-       zv_decompress(virt_to_page(data), pampd);
+       zv_decompress((struct page *)(data), pampd);
        return ret;
 }
 
@@ -1539,7 +1539,7 @@ static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
                goto out;
        if (!zcache_freeze && zcache_do_preload(pool) == 0) {
                /* preload does preempt_disable on success */
-               ret = tmem_put(pool, oidp, index, page_address(page),
+               ret = tmem_put(pool, oidp, index, (char *)(page),
                                PAGE_SIZE, 0, is_ephemeral(pool));
                if (ret < 0) {
                        if (is_ephemeral(pool))
@@ -1572,7 +1572,7 @@ static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp,
        pool = zcache_get_pool_by_id(cli_id, pool_id);
        if (likely(pool != NULL)) {
                if (atomic_read(&pool->obj_count) > 0)
-                       ret = tmem_get(pool, oidp, index, page_address(page),
+                       ret = tmem_get(pool, oidp, index, (char *)(page),
                                        &size, 0, is_ephemeral(pool));
                zcache_put_pool(pool);
        }
index c24fb10..6a4ea29 100644 (file)
@@ -2243,7 +2243,6 @@ static int iscsit_handle_snack(
        case 0:
                return iscsit_handle_recovery_datain_or_r2t(conn, buf,
                        hdr->itt, hdr->ttt, hdr->begrun, hdr->runlength);
-               return 0;
        case ISCSI_FLAG_SNACK_TYPE_STATUS:
                return iscsit_handle_status_snack(conn, hdr->itt, hdr->ttt,
                        hdr->begrun, hdr->runlength);
index f095e65..f1643db 100644 (file)
@@ -268,7 +268,7 @@ struct se_tpg_np *lio_target_call_addnptotpg(
                                ISCSI_TCP);
        if (IS_ERR(tpg_np)) {
                iscsit_put_tpg(tpg);
-               return ERR_PTR(PTR_ERR(tpg_np));
+               return ERR_CAST(tpg_np);
        }
        pr_debug("LIO_Target_ConfigFS: addnptotpg done!\n");
 
@@ -1285,7 +1285,7 @@ struct se_wwn *lio_target_call_coreaddtiqn(
 
        tiqn = iscsit_add_tiqn((unsigned char *)name);
        if (IS_ERR(tiqn))
-               return ERR_PTR(PTR_ERR(tiqn));
+               return ERR_CAST(tiqn);
        /*
         * Setup struct iscsi_wwn_stat_grps for se_wwn->fabric_stat_group.
         */
index 9806507..c4c68da 100644 (file)
@@ -834,7 +834,7 @@ static int iscsit_attach_ooo_cmdsn(
                         */
                        list_for_each_entry(ooo_tmp, &sess->sess_ooo_cmdsn_list,
                                                ooo_list) {
-                               while (ooo_tmp->cmdsn < ooo_cmdsn->cmdsn)
+                               if (ooo_tmp->cmdsn < ooo_cmdsn->cmdsn)
                                        continue;
 
                                list_add(&ooo_cmdsn->ooo_list,
index bcaf82f..daad362 100644 (file)
@@ -1013,19 +1013,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                                        ISCSI_LOGIN_STATUS_TARGET_ERROR);
                        goto new_sess_out;
                }
-#if 0
-               if (!iscsi_ntop6((const unsigned char *)
-                               &sock_in6.sin6_addr.in6_u,
-                               (char *)&conn->ipv6_login_ip[0],
-                               IPV6_ADDRESS_SPACE)) {
-                       pr_err("iscsi_ntop6() failed\n");
-                       iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
-                                       ISCSI_LOGIN_STATUS_TARGET_ERROR);
-                       goto new_sess_out;
-               }
-#else
-               pr_debug("Skipping iscsi_ntop6()\n");
-#endif
+               snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
+                               &sock_in6.sin6_addr.in6_u);
+               conn->login_port = ntohs(sock_in6.sin6_port);
        } else {
                memset(&sock_in, 0, sizeof(struct sockaddr_in));
 
index 252e246..497b2e7 100644 (file)
@@ -545,13 +545,13 @@ int iscsi_copy_param_list(
        struct iscsi_param_list *src_param_list,
        int leading)
 {
-       struct iscsi_param *new_param = NULL, *param = NULL;
+       struct iscsi_param *param = NULL;
+       struct iscsi_param *new_param = NULL;
        struct iscsi_param_list *param_list = NULL;
 
        param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL);
        if (!param_list) {
-               pr_err("Unable to allocate memory for"
-                               " struct iscsi_param_list.\n");
+               pr_err("Unable to allocate memory for struct iscsi_param_list.\n");
                goto err_out;
        }
        INIT_LIST_HEAD(&param_list->param_list);
@@ -567,8 +567,17 @@ int iscsi_copy_param_list(
 
                new_param = kzalloc(sizeof(struct iscsi_param), GFP_KERNEL);
                if (!new_param) {
-                       pr_err("Unable to allocate memory for"
-                               " struct iscsi_param.\n");
+                       pr_err("Unable to allocate memory for struct iscsi_param.\n");
+                       goto err_out;
+               }
+
+               new_param->name = kstrdup(param->name, GFP_KERNEL);
+               new_param->value = kstrdup(param->value, GFP_KERNEL);
+               if (!new_param->value || !new_param->name) {
+                       kfree(new_param->value);
+                       kfree(new_param->name);
+                       kfree(new_param);
+                       pr_err("Unable to allocate memory for parameter name/value.\n");
                        goto err_out;
                }
 
@@ -580,32 +589,12 @@ int iscsi_copy_param_list(
                new_param->use = param->use;
                new_param->type_range = param->type_range;
 
-               new_param->name = kzalloc(strlen(param->name) + 1, GFP_KERNEL);
-               if (!new_param->name) {
-                       pr_err("Unable to allocate memory for"
-                               " parameter name.\n");
-                       goto err_out;
-               }
-
-               new_param->value = kzalloc(strlen(param->value) + 1,
-                               GFP_KERNEL);
-               if (!new_param->value) {
-                       pr_err("Unable to allocate memory for"
-                               " parameter value.\n");
-                       goto err_out;
-               }
-
-               memcpy(new_param->name, param->name, strlen(param->name));
-               new_param->name[strlen(param->name)] = '\0';
-               memcpy(new_param->value, param->value, strlen(param->value));
-               new_param->value[strlen(param->value)] = '\0';
-
                list_add_tail(&new_param->p_list, &param_list->param_list);
        }
 
-       if (!list_empty(&param_list->param_list))
+       if (!list_empty(&param_list->param_list)) {
                *dst_param_list = param_list;
-       else {
+       else {
                pr_err("No parameters allocated.\n");
                goto err_out;
        }
index a1acb01..a0d23bc 100644 (file)
@@ -243,7 +243,7 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
        if (!cmd->tmr_req) {
                pr_err("Unable to allocate memory for"
                        " Task Management command!\n");
-               return NULL;
+               goto out;
        }
        /*
         * TASK_REASSIGN for ERL=2 / connection stays inside of
@@ -298,8 +298,6 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
        return cmd;
 out:
        iscsit_release_cmd(cmd);
-       if (se_cmd)
-               transport_free_se_cmd(se_cmd);
        return NULL;
 }
 
index 8ae09a1..89ae923 100644 (file)
@@ -67,6 +67,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
 {
        struct se_lun *lun = cmd->se_lun;
        struct se_device *dev = cmd->se_dev;
+       struct se_portal_group *tpg = lun->lun_sep->sep_tpg;
        unsigned char *buf;
 
        /*
@@ -81,9 +82,13 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
 
        buf = transport_kmap_first_data_page(cmd);
 
-       buf[0] = dev->transport->get_device_type(dev);
-       if (buf[0] == TYPE_TAPE)
-               buf[1] = 0x80;
+       if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
+               buf[0] = 0x3f; /* Not connected */
+       } else {
+               buf[0] = dev->transport->get_device_type(dev);
+               if (buf[0] == TYPE_TAPE)
+                       buf[1] = 0x80;
+       }
        buf[2] = dev->transport->get_device_rev(dev);
 
        /*
@@ -915,8 +920,8 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
                length += target_modesense_control(dev, &buf[offset+length]);
                break;
        default:
-               pr_err("Got Unknown Mode Page: 0x%02x\n",
-                               cdb[2] & 0x3f);
+               pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
+                      cdb[2] & 0x3f, cdb[3]);
                return PYX_TRANSPORT_UNKNOWN_MODE_PAGE;
        }
        offset += length;
@@ -1072,8 +1077,6 @@ target_emulate_unmap(struct se_task *task)
                size -= 16;
        }
 
-       task->task_scsi_status = GOOD;
-       transport_complete_task(task, 1);
 err:
        transport_kunmap_first_data_page(cmd);
 
@@ -1085,24 +1088,17 @@ err:
  * Note this is not used for TCM/pSCSI passthrough
  */
 static int
-target_emulate_write_same(struct se_task *task, int write_same32)
+target_emulate_write_same(struct se_task *task, u32 num_blocks)
 {
        struct se_cmd *cmd = task->task_se_cmd;
        struct se_device *dev = cmd->se_dev;
        sector_t range;
        sector_t lba = cmd->t_task_lba;
-       unsigned int num_blocks;
        int ret;
        /*
-        * Extract num_blocks from the WRITE_SAME_* CDB.  Then use the explict
-        * range when non zero is supplied, otherwise calculate the remaining
-        * range based on ->get_blocks() - starting LBA.
+        * Use the explicit range when non zero is supplied, otherwise calculate
+        * the remaining range based on ->get_blocks() - starting LBA.
         */
-       if (write_same32)
-               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);
-       else
-               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);
-
        if (num_blocks != 0)
                range = num_blocks;
        else
@@ -1117,8 +1113,6 @@ target_emulate_write_same(struct se_task *task, int write_same32)
                return ret;
        }
 
-       task->task_scsi_status = GOOD;
-       transport_complete_task(task, 1);
        return 0;
 }
 
@@ -1165,13 +1159,23 @@ transport_emulate_control_cdb(struct se_task *task)
                }
                ret = target_emulate_unmap(task);
                break;
+       case WRITE_SAME:
+               if (!dev->transport->do_discard) {
+                       pr_err("WRITE_SAME emulation not supported"
+                                       " for: %s\n", dev->transport->name);
+                       return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+               }
+               ret = target_emulate_write_same(task,
+                               get_unaligned_be16(&cmd->t_task_cdb[7]));
+               break;
        case WRITE_SAME_16:
                if (!dev->transport->do_discard) {
                        pr_err("WRITE_SAME_16 emulation not supported"
                                        " for: %s\n", dev->transport->name);
                        return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                }
-               ret = target_emulate_write_same(task, 0);
+               ret = target_emulate_write_same(task,
+                               get_unaligned_be32(&cmd->t_task_cdb[10]));
                break;
        case VARIABLE_LENGTH_CMD:
                service_action =
@@ -1184,7 +1188,8 @@ transport_emulate_control_cdb(struct se_task *task)
                                        dev->transport->name);
                                return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                        }
-                       ret = target_emulate_write_same(task, 1);
+                       ret = target_emulate_write_same(task,
+                               get_unaligned_be32(&cmd->t_task_cdb[28]));
                        break;
                default:
                        pr_err("Unsupported VARIABLE_LENGTH_CMD SA:"
@@ -1219,8 +1224,14 @@ transport_emulate_control_cdb(struct se_task *task)
 
        if (ret < 0)
                return ret;
-       task->task_scsi_status = GOOD;
-       transport_complete_task(task, 1);
+       /*
+        * Handle the successful completion here unless a caller
+        * has explictly requested an asychronous completion.
+        */
+       if (!(cmd->se_cmd_flags & SCF_EMULATE_CDB_ASYNC)) {
+               task->task_scsi_status = GOOD;
+               transport_complete_task(task, 1);
+       }
 
        return PYX_TRANSPORT_SENT_TO_TRANSPORT;
 }
index b38b6c9..ca6e4a4 100644 (file)
@@ -472,9 +472,9 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg)
        struct se_dev_entry *deve;
        u32 i;
 
-       spin_lock_bh(&tpg->acl_node_lock);
+       spin_lock_irq(&tpg->acl_node_lock);
        list_for_each_entry(nacl, &tpg->acl_node_list, acl_list) {
-               spin_unlock_bh(&tpg->acl_node_lock);
+               spin_unlock_irq(&tpg->acl_node_lock);
 
                spin_lock_irq(&nacl->device_list_lock);
                for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
@@ -491,9 +491,9 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg)
                }
                spin_unlock_irq(&nacl->device_list_lock);
 
-               spin_lock_bh(&tpg->acl_node_lock);
+               spin_lock_irq(&tpg->acl_node_lock);
        }
-       spin_unlock_bh(&tpg->acl_node_lock);
+       spin_unlock_irq(&tpg->acl_node_lock);
 }
 
 static struct se_port *core_alloc_port(struct se_device *dev)
@@ -839,6 +839,24 @@ int se_dev_check_shutdown(struct se_device *dev)
        return ret;
 }
 
+u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
+{
+       u32 tmp, aligned_max_sectors;
+       /*
+        * Limit max_sectors to a PAGE_SIZE aligned value for modern
+        * transport_allocate_data_tasks() operation.
+        */
+       tmp = rounddown((max_sectors * block_size), PAGE_SIZE);
+       aligned_max_sectors = (tmp / block_size);
+       if (max_sectors != aligned_max_sectors) {
+               printk(KERN_INFO "Rounding down aligned max_sectors from %u"
+                               " to %u\n", max_sectors, aligned_max_sectors);
+               return aligned_max_sectors;
+       }
+
+       return max_sectors;
+}
+
 void se_dev_set_default_attribs(
        struct se_device *dev,
        struct se_dev_limits *dev_limits)
@@ -878,6 +896,11 @@ void se_dev_set_default_attribs(
         * max_sectors is based on subsystem plugin dependent requirements.
         */
        dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors;
+       /*
+        * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
+        */
+       limits->max_sectors = se_dev_align_max_sectors(limits->max_sectors,
+                                               limits->logical_block_size);
        dev->se_sub_dev->se_dev_attrib.max_sectors = limits->max_sectors;
        /*
         * Set optimal_sectors from max_sectors, which can be lowered via
@@ -1242,6 +1265,11 @@ int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors)
                        return -EINVAL;
                }
        }
+       /*
+        * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
+        */
+       max_sectors = se_dev_align_max_sectors(max_sectors,
+                               dev->se_sub_dev->se_dev_attrib.block_size);
 
        dev->se_sub_dev->se_dev_attrib.max_sectors = max_sectors;
        pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
@@ -1344,15 +1372,17 @@ struct se_lun *core_dev_add_lun(
         */
        if (tpg->se_tpg_tfo->tpg_check_demo_mode(tpg)) {
                struct se_node_acl *acl;
-               spin_lock_bh(&tpg->acl_node_lock);
+               spin_lock_irq(&tpg->acl_node_lock);
                list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
-                       if (acl->dynamic_node_acl) {
-                               spin_unlock_bh(&tpg->acl_node_lock);
+                       if (acl->dynamic_node_acl &&
+                           (!tpg->se_tpg_tfo->tpg_check_demo_mode_login_only ||
+                            !tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg))) {
+                               spin_unlock_irq(&tpg->acl_node_lock);
                                core_tpg_add_node_to_devs(acl, tpg);
-                               spin_lock_bh(&tpg->acl_node_lock);
+                               spin_lock_irq(&tpg->acl_node_lock);
                        }
                }
-               spin_unlock_bh(&tpg->acl_node_lock);
+               spin_unlock_irq(&tpg->acl_node_lock);
        }
 
        return lun_p;
index f165469..55bbe08 100644 (file)
@@ -481,7 +481,7 @@ static struct config_group *target_fabric_make_nodeacl(
 
        se_nacl = tf->tf_ops.fabric_make_nodeacl(se_tpg, group, name);
        if (IS_ERR(se_nacl))
-               return ERR_PTR(PTR_ERR(se_nacl));
+               return ERR_CAST(se_nacl);
 
        nacl_cg = &se_nacl->acl_group;
        nacl_cg->default_groups = se_nacl->acl_default_groups;
index 1c1b849..7fd3a16 100644 (file)
@@ -1598,14 +1598,14 @@ static int core_scsi3_decode_spec_i_port(
                         * from the decoded fabric module specific TransportID
                         * at *i_str.
                         */
-                       spin_lock_bh(&tmp_tpg->acl_node_lock);
+                       spin_lock_irq(&tmp_tpg->acl_node_lock);
                        dest_node_acl = __core_tpg_get_initiator_node_acl(
                                                tmp_tpg, i_str);
                        if (dest_node_acl) {
                                atomic_inc(&dest_node_acl->acl_pr_ref_count);
                                smp_mb__after_atomic_inc();
                        }
-                       spin_unlock_bh(&tmp_tpg->acl_node_lock);
+                       spin_unlock_irq(&tmp_tpg->acl_node_lock);
 
                        if (!dest_node_acl) {
                                core_scsi3_tpg_undepend_item(tmp_tpg);
@@ -3496,14 +3496,14 @@ after_iport_check:
        /*
         * Locate the destination struct se_node_acl from the received Transport ID
         */
-       spin_lock_bh(&dest_se_tpg->acl_node_lock);
+       spin_lock_irq(&dest_se_tpg->acl_node_lock);
        dest_node_acl = __core_tpg_get_initiator_node_acl(dest_se_tpg,
                                initiator_str);
        if (dest_node_acl) {
                atomic_inc(&dest_node_acl->acl_pr_ref_count);
                smp_mb__after_atomic_inc();
        }
-       spin_unlock_bh(&dest_se_tpg->acl_node_lock);
+       spin_unlock_irq(&dest_se_tpg->acl_node_lock);
 
        if (!dest_node_acl) {
                pr_err("Unable to locate %s dest_node_acl for"
index 3dd81d2..e567e12 100644 (file)
@@ -390,12 +390,10 @@ static int rd_MEMCPY_read(struct rd_request *req)
                                length = req->rd_size;
 
                        dst = sg_virt(&sg_d[i++]) + dst_offset;
-                       if (!dst)
-                               BUG();
+                       BUG_ON(!dst);
 
                        src = sg_virt(&sg_s[j]) + src_offset;
-                       if (!src)
-                               BUG();
+                       BUG_ON(!src);
 
                        dst_offset = 0;
                        src_offset = length;
@@ -415,8 +413,7 @@ static int rd_MEMCPY_read(struct rd_request *req)
                                length = req->rd_size;
 
                        dst = sg_virt(&sg_d[i]) + dst_offset;
-                       if (!dst)
-                               BUG();
+                       BUG_ON(!dst);
 
                        if (sg_d[i].length == length) {
                                i++;
@@ -425,8 +422,7 @@ static int rd_MEMCPY_read(struct rd_request *req)
                                dst_offset = length;
 
                        src = sg_virt(&sg_s[j++]) + src_offset;
-                       if (!src)
-                               BUG();
+                       BUG_ON(!src);
 
                        src_offset = 0;
                        page_end = 1;
@@ -510,12 +506,10 @@ static int rd_MEMCPY_write(struct rd_request *req)
                                length = req->rd_size;
 
                        src = sg_virt(&sg_s[i++]) + src_offset;
-                       if (!src)
-                               BUG();
+                       BUG_ON(!src);
 
                        dst = sg_virt(&sg_d[j]) + dst_offset;
-                       if (!dst)
-                               BUG();
+                       BUG_ON(!dst);
 
                        src_offset = 0;
                        dst_offset = length;
@@ -535,8 +529,7 @@ static int rd_MEMCPY_write(struct rd_request *req)
                                length = req->rd_size;
 
                        src = sg_virt(&sg_s[i]) + src_offset;
-                       if (!src)
-                               BUG();
+                       BUG_ON(!src);
 
                        if (sg_s[i].length == length) {
                                i++;
@@ -545,8 +538,7 @@ static int rd_MEMCPY_write(struct rd_request *req)
                                src_offset = length;
 
                        dst = sg_virt(&sg_d[j++]) + dst_offset;
-                       if (!dst)
-                               BUG();
+                       BUG_ON(!dst);
 
                        dst_offset = 0;
                        page_end = 1;
index 4f1ba4c..162b736 100644 (file)
@@ -137,15 +137,15 @@ struct se_node_acl *core_tpg_get_initiator_node_acl(
 {
        struct se_node_acl *acl;
 
-       spin_lock_bh(&tpg->acl_node_lock);
+       spin_lock_irq(&tpg->acl_node_lock);
        list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
                if (!strcmp(acl->initiatorname, initiatorname) &&
                    !acl->dynamic_node_acl) {
-                       spin_unlock_bh(&tpg->acl_node_lock);
+                       spin_unlock_irq(&tpg->acl_node_lock);
                        return acl;
                }
        }
-       spin_unlock_bh(&tpg->acl_node_lock);
+       spin_unlock_irq(&tpg->acl_node_lock);
 
        return NULL;
 }
@@ -298,13 +298,21 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
                tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
                return NULL;
        }
+       /*
+        * Here we only create demo-mode MappedLUNs from the active
+        * TPG LUNs if the fabric is not explictly asking for
+        * tpg_check_demo_mode_login_only() == 1.
+        */
+       if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only != NULL) &&
+           (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) == 1))
+               do { ; } while (0);
+       else
+               core_tpg_add_node_to_devs(acl, tpg);
 
-       core_tpg_add_node_to_devs(acl, tpg);
-
-       spin_lock_bh(&tpg->acl_node_lock);
+       spin_lock_irq(&tpg->acl_node_lock);
        list_add_tail(&acl->acl_list, &tpg->acl_node_list);
        tpg->num_node_acls++;
-       spin_unlock_bh(&tpg->acl_node_lock);
+       spin_unlock_irq(&tpg->acl_node_lock);
 
        pr_debug("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s"
                " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
@@ -354,7 +362,7 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
 {
        struct se_node_acl *acl = NULL;
 
-       spin_lock_bh(&tpg->acl_node_lock);
+       spin_lock_irq(&tpg->acl_node_lock);
        acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
        if (acl) {
                if (acl->dynamic_node_acl) {
@@ -362,7 +370,7 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
                        pr_debug("%s_TPG[%u] - Replacing dynamic ACL"
                                " for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
                                tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname);
-                       spin_unlock_bh(&tpg->acl_node_lock);
+                       spin_unlock_irq(&tpg->acl_node_lock);
                        /*
                         * Release the locally allocated struct se_node_acl
                         * because * core_tpg_add_initiator_node_acl() returned
@@ -378,10 +386,10 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
                        " Node %s already exists for TPG %u, ignoring"
                        " request.\n",  tpg->se_tpg_tfo->get_fabric_name(),
                        initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
-               spin_unlock_bh(&tpg->acl_node_lock);
+               spin_unlock_irq(&tpg->acl_node_lock);
                return ERR_PTR(-EEXIST);
        }
-       spin_unlock_bh(&tpg->acl_node_lock);
+       spin_unlock_irq(&tpg->acl_node_lock);
 
        if (!se_nacl) {
                pr_err("struct se_node_acl pointer is NULL\n");
@@ -418,10 +426,10 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
                return ERR_PTR(-EINVAL);
        }
 
-       spin_lock_bh(&tpg->acl_node_lock);
+       spin_lock_irq(&tpg->acl_node_lock);
        list_add_tail(&acl->acl_list, &tpg->acl_node_list);
        tpg->num_node_acls++;
-       spin_unlock_bh(&tpg->acl_node_lock);
+       spin_unlock_irq(&tpg->acl_node_lock);
 
 done:
        pr_debug("%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s"
@@ -445,14 +453,14 @@ int core_tpg_del_initiator_node_acl(
        struct se_session *sess, *sess_tmp;
        int dynamic_acl = 0;
 
-       spin_lock_bh(&tpg->acl_node_lock);
+       spin_lock_irq(&tpg->acl_node_lock);
        if (acl->dynamic_node_acl) {
                acl->dynamic_node_acl = 0;
                dynamic_acl = 1;
        }
        list_del(&acl->acl_list);
        tpg->num_node_acls--;
-       spin_unlock_bh(&tpg->acl_node_lock);
+       spin_unlock_irq(&tpg->acl_node_lock);
 
        spin_lock_bh(&tpg->session_lock);
        list_for_each_entry_safe(sess, sess_tmp,
@@ -503,21 +511,21 @@ int core_tpg_set_initiator_node_queue_depth(
        struct se_node_acl *acl;
        int dynamic_acl = 0;
 
-       spin_lock_bh(&tpg->acl_node_lock);
+       spin_lock_irq(&tpg->acl_node_lock);
        acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
        if (!acl) {
                pr_err("Access Control List entry for %s Initiator"
                        " Node %s does not exists for TPG %hu, ignoring"
                        " request.\n", tpg->se_tpg_tfo->get_fabric_name(),
                        initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
-               spin_unlock_bh(&tpg->acl_node_lock);
+               spin_unlock_irq(&tpg->acl_node_lock);
                return -ENODEV;
        }
        if (acl->dynamic_node_acl) {
                acl->dynamic_node_acl = 0;
                dynamic_acl = 1;
        }
-       spin_unlock_bh(&tpg->acl_node_lock);
+       spin_unlock_irq(&tpg->acl_node_lock);
 
        spin_lock_bh(&tpg->session_lock);
        list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) {
@@ -533,10 +541,10 @@ int core_tpg_set_initiator_node_queue_depth(
                                tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
                        spin_unlock_bh(&tpg->session_lock);
 
-                       spin_lock_bh(&tpg->acl_node_lock);
+                       spin_lock_irq(&tpg->acl_node_lock);
                        if (dynamic_acl)
                                acl->dynamic_node_acl = 1;
-                       spin_unlock_bh(&tpg->acl_node_lock);
+                       spin_unlock_irq(&tpg->acl_node_lock);
                        return -EEXIST;
                }
                /*
@@ -571,10 +579,10 @@ int core_tpg_set_initiator_node_queue_depth(
                if (init_sess)
                        tpg->se_tpg_tfo->close_session(init_sess);
 
-               spin_lock_bh(&tpg->acl_node_lock);
+               spin_lock_irq(&tpg->acl_node_lock);
                if (dynamic_acl)
                        acl->dynamic_node_acl = 1;
-               spin_unlock_bh(&tpg->acl_node_lock);
+               spin_unlock_irq(&tpg->acl_node_lock);
                return -EINVAL;
        }
        spin_unlock_bh(&tpg->session_lock);
@@ -590,10 +598,10 @@ int core_tpg_set_initiator_node_queue_depth(
                initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
                tpg->se_tpg_tfo->tpg_get_tag(tpg));
 
-       spin_lock_bh(&tpg->acl_node_lock);
+       spin_lock_irq(&tpg->acl_node_lock);
        if (dynamic_acl)
                acl->dynamic_node_acl = 1;
-       spin_unlock_bh(&tpg->acl_node_lock);
+       spin_unlock_irq(&tpg->acl_node_lock);
 
        return 0;
 }
@@ -717,20 +725,20 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
         * not been released because of TFO->tpg_check_demo_mode_cache() == 1
         * in transport_deregister_session().
         */
-       spin_lock_bh(&se_tpg->acl_node_lock);
+       spin_lock_irq(&se_tpg->acl_node_lock);
        list_for_each_entry_safe(nacl, nacl_tmp, &se_tpg->acl_node_list,
                        acl_list) {
                list_del(&nacl->acl_list);
                se_tpg->num_node_acls--;
-               spin_unlock_bh(&se_tpg->acl_node_lock);
+               spin_unlock_irq(&se_tpg->acl_node_lock);
 
                core_tpg_wait_for_nacl_pr_ref(nacl);
                core_free_device_list_for_node(nacl, se_tpg);
                se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, nacl);
 
-               spin_lock_bh(&se_tpg->acl_node_lock);
+               spin_lock_irq(&se_tpg->acl_node_lock);
        }
-       spin_unlock_bh(&se_tpg->acl_node_lock);
+       spin_unlock_irq(&se_tpg->acl_node_lock);
 
        if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL)
                core_tpg_release_virtual_lun0(se_tpg);
index 8976032..8d0c58e 100644 (file)
@@ -389,17 +389,18 @@ void transport_deregister_session(struct se_session *se_sess)
 {
        struct se_portal_group *se_tpg = se_sess->se_tpg;
        struct se_node_acl *se_nacl;
+       unsigned long flags;
 
        if (!se_tpg) {
                transport_free_session(se_sess);
                return;
        }
 
-       spin_lock_bh(&se_tpg->session_lock);
+       spin_lock_irqsave(&se_tpg->session_lock, flags);
        list_del(&se_sess->sess_list);
        se_sess->se_tpg = NULL;
        se_sess->fabric_sess_ptr = NULL;
-       spin_unlock_bh(&se_tpg->session_lock);
+       spin_unlock_irqrestore(&se_tpg->session_lock, flags);
 
        /*
         * Determine if we need to do extra work for this initiator node's
@@ -407,22 +408,22 @@ void transport_deregister_session(struct se_session *se_sess)
         */
        se_nacl = se_sess->se_node_acl;
        if (se_nacl) {
-               spin_lock_bh(&se_tpg->acl_node_lock);
+               spin_lock_irqsave(&se_tpg->acl_node_lock, flags);
                if (se_nacl->dynamic_node_acl) {
                        if (!se_tpg->se_tpg_tfo->tpg_check_demo_mode_cache(
                                        se_tpg)) {
                                list_del(&se_nacl->acl_list);
                                se_tpg->num_node_acls--;
-                               spin_unlock_bh(&se_tpg->acl_node_lock);
+                               spin_unlock_irqrestore(&se_tpg->acl_node_lock, flags);
 
                                core_tpg_wait_for_nacl_pr_ref(se_nacl);
                                core_free_device_list_for_node(se_nacl, se_tpg);
                                se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg,
                                                se_nacl);
-                               spin_lock_bh(&se_tpg->acl_node_lock);
+                               spin_lock_irqsave(&se_tpg->acl_node_lock, flags);
                        }
                }
-               spin_unlock_bh(&se_tpg->acl_node_lock);
+               spin_unlock_irqrestore(&se_tpg->acl_node_lock, flags);
        }
 
        transport_free_session(se_sess);
@@ -2053,8 +2054,14 @@ static void transport_generic_request_failure(
                cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
                break;
        }
-
-       if (!sc)
+       /*
+        * If a fabric does not define a cmd->se_tfo->new_cmd_map caller,
+        * make the call to transport_send_check_condition_and_sense()
+        * directly.  Otherwise expect the fabric to make the call to
+        * transport_send_check_condition_and_sense() after handling
+        * possible unsoliticied write data payloads.
+        */
+       if (!sc && !cmd->se_tfo->new_cmd_map)
                transport_new_cmd_failure(cmd);
        else {
                ret = transport_send_check_condition_and_sense(cmd,
@@ -2847,12 +2854,42 @@ static int transport_cmd_get_valid_sectors(struct se_cmd *cmd)
                        " transport_dev_end_lba(): %llu\n",
                        cmd->t_task_lba, sectors,
                        transport_dev_end_lba(dev));
-               pr_err("  We should return CHECK_CONDITION"
-                      " but we don't yet\n");
-               return 0;
+               return -EINVAL;
        }
 
-       return sectors;
+       return 0;
+}
+
+static int target_check_write_same_discard(unsigned char *flags, struct se_device *dev)
+{
+       /*
+        * Determine if the received WRITE_SAME is used to for direct
+        * passthrough into Linux/SCSI with struct request via TCM/pSCSI
+        * or we are signaling the use of internal WRITE_SAME + UNMAP=1
+        * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK code.
+        */
+       int passthrough = (dev->transport->transport_type ==
+                               TRANSPORT_PLUGIN_PHBA_PDEV);
+
+       if (!passthrough) {
+               if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
+                       pr_err("WRITE_SAME PBDATA and LBDATA"
+                               " bits not supported for Block Discard"
+                               " Emulation\n");
+                       return -ENOSYS;
+               }
+               /*
+                * Currently for the emulated case we only accept
+                * tpws with the UNMAP=1 bit set.
+                */
+               if (!(flags[0] & 0x08)) {
+                       pr_err("WRITE_SAME w/o UNMAP bit not"
+                               " supported for Block Discard Emulation\n");
+                       return -ENOSYS;
+               }
+       }
+
+       return 0;
 }
 
 /*     transport_generic_cmd_sequencer():
@@ -3065,7 +3102,7 @@ static int transport_generic_cmd_sequencer(
                                goto out_unsupported_cdb;
 
                        if (sectors)
-                               size = transport_get_size(sectors, cdb, cmd);
+                               size = transport_get_size(1, cdb, cmd);
                        else {
                                pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
                                       " supported\n");
@@ -3075,27 +3112,9 @@ static int transport_generic_cmd_sequencer(
                        cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
                        cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 
-                       /*
-                        * Skip the remaining assignments for TCM/PSCSI passthrough
-                        */
-                       if (passthrough)
-                               break;
-
-                       if ((cdb[10] & 0x04) || (cdb[10] & 0x02)) {
-                               pr_err("WRITE_SAME PBDATA and LBDATA"
-                                       " bits not supported for Block Discard"
-                                       " Emulation\n");
+                       if (target_check_write_same_discard(&cdb[10], dev) < 0)
                                goto out_invalid_cdb_field;
-                       }
-                       /*
-                        * Currently for the emulated case we only accept
-                        * tpws with the UNMAP=1 bit set.
-                        */
-                       if (!(cdb[10] & 0x08)) {
-                               pr_err("WRITE_SAME w/o UNMAP bit not"
-                                       " supported for Block Discard Emulation\n");
-                               goto out_invalid_cdb_field;
-                       }
+
                        break;
                default:
                        pr_err("VARIABLE_LENGTH_CMD service action"
@@ -3330,10 +3349,12 @@ static int transport_generic_cmd_sequencer(
                cmd->se_cmd_flags |= SCF_EMULATE_CDB_ASYNC;
                /*
                 * Check to ensure that LBA + Range does not exceed past end of
-                * device.
+                * device for IBLOCK and FILEIO ->do_sync_cache() backend calls
                 */
-               if (!transport_cmd_get_valid_sectors(cmd))
-                       goto out_invalid_cdb_field;
+               if ((cmd->t_task_lba != 0) || (sectors != 0)) {
+                       if (transport_cmd_get_valid_sectors(cmd) < 0)
+                               goto out_invalid_cdb_field;
+               }
                break;
        case UNMAP:
                size = get_unaligned_be16(&cdb[7]);
@@ -3345,40 +3366,38 @@ static int transport_generic_cmd_sequencer(
                        goto out_unsupported_cdb;
 
                if (sectors)
-                       size = transport_get_size(sectors, cdb, cmd);
+                       size = transport_get_size(1, cdb, cmd);
                else {
                        pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
                        goto out_invalid_cdb_field;
                }
 
                cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
-               passthrough = (dev->transport->transport_type ==
-                               TRANSPORT_PLUGIN_PHBA_PDEV);
-               /*
-                * Determine if the received WRITE_SAME_16 is used to for direct
-                * passthrough into Linux/SCSI with struct request via TCM/pSCSI
-                * or we are signaling the use of internal WRITE_SAME + UNMAP=1
-                * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK and
-                * TCM/FILEIO subsystem plugin backstores.
-                */
-               if (!passthrough) {
-                       if ((cdb[1] & 0x04) || (cdb[1] & 0x02)) {
-                               pr_err("WRITE_SAME PBDATA and LBDATA"
-                                       " bits not supported for Block Discard"
-                                       " Emulation\n");
-                               goto out_invalid_cdb_field;
-                       }
-                       /*
-                        * Currently for the emulated case we only accept
-                        * tpws with the UNMAP=1 bit set.
-                        */
-                       if (!(cdb[1] & 0x08)) {
-                               pr_err("WRITE_SAME w/o UNMAP bit not "
-                                       " supported for Block Discard Emulation\n");
-                               goto out_invalid_cdb_field;
-                       }
+               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+
+               if (target_check_write_same_discard(&cdb[1], dev) < 0)
+                       goto out_invalid_cdb_field;
+               break;
+       case WRITE_SAME:
+               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
+               if (sector_ret)
+                       goto out_unsupported_cdb;
+
+               if (sectors)
+                       size = transport_get_size(1, cdb, cmd);
+               else {
+                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
+                       goto out_invalid_cdb_field;
                }
+
+               cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
                cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+               /*
+                * Follow sbcr26 with WRITE_SAME (10) and check for the existence
+                * of byte 1 bit 3 UNMAP instead of original reserved field
+                */
+               if (target_check_write_same_discard(&cdb[1], dev) < 0)
+                       goto out_invalid_cdb_field;
                break;
        case ALLOW_MEDIUM_REMOVAL:
        case GPCMD_CLOSE_TRACK:
@@ -3873,9 +3892,7 @@ EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
 static int transport_new_cmd_obj(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
-       u32 task_cdbs;
-       u32 rc;
-       int set_counts = 1;
+       int set_counts = 1, rc, task_cdbs;
 
        /*
         * Setup any BIDI READ tasks and memory from
@@ -3893,7 +3910,7 @@ static int transport_new_cmd_obj(struct se_cmd *cmd)
                        cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
                        cmd->scsi_sense_reason =
                                TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-                       return PYX_TRANSPORT_LU_COMM_FAILURE;
+                       return -EINVAL;
                }
                atomic_inc(&cmd->t_fe_count);
                atomic_inc(&cmd->t_se_count);
@@ -3912,7 +3929,7 @@ static int transport_new_cmd_obj(struct se_cmd *cmd)
                cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
                cmd->scsi_sense_reason =
                        TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-               return PYX_TRANSPORT_LU_COMM_FAILURE;
+               return -EINVAL;
        }
 
        if (set_counts) {
@@ -4028,8 +4045,6 @@ void transport_do_task_sg_chain(struct se_cmd *cmd)
                if (!task->task_sg)
                        continue;
 
-               BUG_ON(!task->task_padded_sg);
-
                if (!sg_first) {
                        sg_first = task->task_sg;
                        chained_nents = task->task_sg_nents;
@@ -4037,9 +4052,19 @@ void transport_do_task_sg_chain(struct se_cmd *cmd)
                        sg_chain(sg_prev, sg_prev_nents, task->task_sg);
                        chained_nents += task->task_sg_nents;
                }
+               /*
+                * For the padded tasks, use the extra SGL vector allocated
+                * in transport_allocate_data_tasks() for the sg_prev_nents
+                * offset into sg_chain() above..  The last task of a
+                * multi-task list, or a single task will not have
+                * task->task_sg_padded set..
+                */
+               if (task->task_padded_sg)
+                       sg_prev_nents = (task->task_sg_nents + 1);
+               else
+                       sg_prev_nents = task->task_sg_nents;
 
                sg_prev = task->task_sg;
-               sg_prev_nents = task->task_sg_nents;
        }
        /*
         * Setup the starting pointer and total t_tasks_sg_linked_no including
@@ -4091,7 +4116,7 @@ static int transport_allocate_data_tasks(
        
        cmd_sg = sgl;
        for (i = 0; i < task_count; i++) {
-               unsigned int task_size;
+               unsigned int task_size, task_sg_nents_padded;
                int count;
 
                task = transport_generic_get_task(cmd, data_direction);
@@ -4110,30 +4135,33 @@ static int transport_allocate_data_tasks(
 
                /* Update new cdb with updated lba/sectors */
                cmd->transport_split_cdb(task->task_lba, task->task_sectors, cdb);
-
+               /*
+                * This now assumes that passed sg_ents are in PAGE_SIZE chunks
+                * in order to calculate the number per task SGL entries
+                */
+               task->task_sg_nents = DIV_ROUND_UP(task->task_size, PAGE_SIZE);
                /*
                 * Check if the fabric module driver is requesting that all
                 * struct se_task->task_sg[] be chained together..  If so,
                 * then allocate an extra padding SG entry for linking and
-                * marking the end of the chained SGL.
-                * Possibly over-allocate task sgl size by using cmd sgl size.
-                * It's so much easier and only a waste when task_count > 1.
-                * That is extremely rare.
+                * marking the end of the chained SGL for every task except
+                * the last one for (task_count > 1) operation, or skipping
+                * the extra padding for the (task_count == 1) case.
                 */
-               task->task_sg_nents = sgl_nents;
-               if (cmd->se_tfo->task_sg_chaining) {
-                       task->task_sg_nents++;
+               if (cmd->se_tfo->task_sg_chaining && (i < (task_count - 1))) {
+                       task_sg_nents_padded = (task->task_sg_nents + 1);
                        task->task_padded_sg = 1;
-               }
+               } else
+                       task_sg_nents_padded = task->task_sg_nents;
 
                task->task_sg = kmalloc(sizeof(struct scatterlist) *
-                                       task->task_sg_nents, GFP_KERNEL);
+                                       task_sg_nents_padded, GFP_KERNEL);
                if (!task->task_sg) {
                        cmd->se_dev->transport->free_task(task);
                        return -ENOMEM;
                }
 
-               sg_init_table(task->task_sg, task->task_sg_nents);
+               sg_init_table(task->task_sg, task_sg_nents_padded);
 
                task_size = task->task_size;
 
@@ -4230,10 +4258,13 @@ static u32 transport_allocate_tasks(
        struct scatterlist *sgl,
        unsigned int sgl_nents)
 {
-       if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)
+       if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
+               if (transport_cmd_get_valid_sectors(cmd) < 0)
+                       return -EINVAL;
+
                return transport_allocate_data_tasks(cmd, lba, data_direction,
                                                     sgl, sgl_nents);
-       else
+       else
                return transport_allocate_control_task(cmd);
 
 }
@@ -4726,6 +4757,13 @@ int transport_send_check_condition_and_sense(
         */
        switch (reason) {
        case TCM_NON_EXISTENT_LUN:
+               /* CURRENT ERROR */
+               buffer[offset] = 0x70;
+               /* ILLEGAL REQUEST */
+               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               /* LOGICAL UNIT NOT SUPPORTED */
+               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x25;
+               break;
        case TCM_UNSUPPORTED_SCSI_OPCODE:
        case TCM_SECTOR_COUNT_TOO_MANY:
                /* CURRENT ERROR */
index 8781d1e..b15879d 100644 (file)
@@ -256,7 +256,7 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata)
        struct se_portal_group *se_tpg = &tpg->se_tpg;
        struct se_node_acl *se_acl;
 
-       spin_lock_bh(&se_tpg->acl_node_lock);
+       spin_lock_irq(&se_tpg->acl_node_lock);
        list_for_each_entry(se_acl, &se_tpg->acl_node_list, acl_list) {
                acl = container_of(se_acl, struct ft_node_acl, se_node_acl);
                pr_debug("acl %p port_name %llx\n",
@@ -270,7 +270,7 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata)
                        break;
                }
        }
-       spin_unlock_bh(&se_tpg->acl_node_lock);
+       spin_unlock_irq(&se_tpg->acl_node_lock);
        return found;
 }
 
@@ -655,9 +655,7 @@ static void __exit ft_exit(void)
        synchronize_rcu();
 }
 
-#ifdef MODULE
 MODULE_DESCRIPTION("FC TCM fabric driver " FT_VERSION);
 MODULE_LICENSE("GPL");
 module_init(ft_init);
 module_exit(ft_exit);
-#endif /* MODULE */
index 98b6e3b..e809e9d 100644 (file)
@@ -446,8 +446,19 @@ static inline void legacy_pty_init(void) { }
 int pty_limit = NR_UNIX98_PTY_DEFAULT;
 static int pty_limit_min;
 static int pty_limit_max = NR_UNIX98_PTY_MAX;
+static int tty_count;
 static int pty_count;
 
+static inline void pty_inc_count(void)
+{
+       pty_count = (++tty_count) / 2;
+}
+
+static inline void pty_dec_count(void)
+{
+       pty_count = (--tty_count) / 2;
+}
+
 static struct cdev ptmx_cdev;
 
 static struct ctl_table pty_table[] = {
@@ -542,6 +553,7 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
 
 static void pty_unix98_shutdown(struct tty_struct *tty)
 {
+       tty_driver_remove_tty(tty->driver, tty);
        /* We have our own method as we don't use the tty index */
        kfree(tty->termios);
 }
@@ -588,7 +600,8 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
         */
        tty_driver_kref_get(driver);
        tty->count++;
-       pty_count++;
+       pty_inc_count(); /* tty */
+       pty_inc_count(); /* tty->link */
        return 0;
 err_free_mem:
        deinitialize_tty_struct(o_tty);
@@ -602,7 +615,7 @@ err_free_tty:
 
 static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
 {
-       pty_count--;
+       pty_dec_count();
 }
 
 static const struct tty_operations ptm_unix98_ops = {
index f2dfec8..7f50999 100644 (file)
@@ -1819,6 +1819,8 @@ static void serial8250_backup_timeout(unsigned long data)
        unsigned int iir, ier = 0, lsr;
        unsigned long flags;
 
+       spin_lock_irqsave(&up->port.lock, flags);
+
        /*
         * Must disable interrupts or else we risk racing with the interrupt
         * based handler.
@@ -1836,10 +1838,8 @@ static void serial8250_backup_timeout(unsigned long data)
         * the "Diva" UART used on the management processor on many HP
         * ia64 and parisc boxes.
         */
-       spin_lock_irqsave(&up->port.lock, flags);
        lsr = serial_in(up, UART_LSR);
        up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-       spin_unlock_irqrestore(&up->port.lock, flags);
        if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
            (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
            (lsr & UART_LSR_THRE)) {
@@ -1848,11 +1848,13 @@ static void serial8250_backup_timeout(unsigned long data)
        }
 
        if (!(iir & UART_IIR_NO_INT))
-               serial8250_handle_port(up);
+               transmit_chars(up);
 
        if (is_real_interrupt(up->port.irq))
                serial_out(up, UART_IER, ier);
 
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
        /* Standard timer interval plus 0.2s to keep the port running */
        mod_timer(&up->timer,
                jiffies + uart_poll_timeout(&up->port) + HZ / 5);
index 6b887d9..3abeca2 100644 (file)
@@ -1599,11 +1599,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .device         = 0x800D,
                .init           = pci_eg20t_init,
        },
-       {
-               .vendor         = 0x10DB,
-               .device         = 0x800D,
-               .init           = pci_eg20t_init,
-       },
        /*
         * Cronyx Omega PCI (PLX-chip based)
         */
@@ -4021,13 +4016,17 @@ static struct pci_device_id serial_pci_tbl[] = {
                0, 0, pbn_NETMOS9900_2s_115200 },
 
        /*
-        * Best Connectivity PCI Multi I/O cards
+        * Best Connectivity and Rosewill PCI Multi I/O cards
         */
 
        {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
                0xA000, 0x1000,
                0, 0, pbn_b0_1_115200 },
 
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+               0xA000, 0x3002,
+               0, 0, pbn_b0_bt_2_115200 },
+
        {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
                0xA000, 0x3004,
                0, 0, pbn_b0_bt_4_115200 },
index fc301f6..a2f2365 100644 (file)
@@ -109,6 +109,9 @@ static const struct pnp_device_id pnp_dev_table[] = {
        /* IBM */
        /* IBM Thinkpad 701 Internal Modem Voice */
        {       "IBM0033",              0       },
+       /* Intermec */
+       /* Intermec CV60 touchscreen port */
+       {       "PNP4972",              0       },
        /* Intertex */
        /* Intertex 28k8 33k6 Voice EXT PnP */
        {       "IXDC801",              0       },
index af9b781..b922f5d 100644 (file)
@@ -1609,9 +1609,11 @@ static struct console atmel_console = {
 static int __init atmel_console_init(void)
 {
        if (atmel_default_console_device) {
-               add_preferred_console(ATMEL_DEVICENAME,
-                                     atmel_default_console_device->id, NULL);
-               atmel_init_port(&atmel_ports[atmel_default_console_device->id],
+               struct atmel_uart_data *pdata =
+                       atmel_default_console_device->dev.platform_data;
+
+               add_preferred_console(ATMEL_DEVICENAME, pdata->num, NULL);
+               atmel_init_port(&atmel_ports[pdata->num],
                                atmel_default_console_device);
                register_console(&atmel_console);
        }
index a1fe304..d73aadd 100644 (file)
@@ -340,5 +340,5 @@ module_exit(max3107_exit);
 
 MODULE_DESCRIPTION("MAX3107 driver");
 MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("aava-max3107-spi");
+MODULE_ALIAS("spi:aava-max3107");
 MODULE_LICENSE("GPL v2");
index 750b4f6..a816460 100644 (file)
@@ -1209,5 +1209,5 @@ module_exit(max3107_exit);
 
 MODULE_DESCRIPTION("MAX3107 driver");
 MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("max3107-spi");
+MODULE_ALIAS("spi:max3107");
 MODULE_LICENSE("GPL v2");
index a764bf9..23bc743 100644 (file)
@@ -917,4 +917,4 @@ module_init(serial_m3110_init);
 module_exit(serial_m3110_exit);
 
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("max3110-uart");
+MODULE_ALIAS("spi:max3110-uart");
index c37df8d..5e713d3 100644 (file)
@@ -806,8 +806,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
        serial_omap_set_mctrl(&up->port, up->port.mctrl);
        /* Software Flow Control Configuration */
-       if (termios->c_iflag & (IXON | IXOFF))
-               serial_omap_configure_xonxoff(up, termios);
+       serial_omap_configure_xonxoff(up, termios);
 
        spin_unlock_irqrestore(&up->port.lock, flags);
        dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id);
index 846dfcd..b46218d 100644 (file)
@@ -598,7 +598,8 @@ static void pch_request_dma(struct uart_port *port)
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
-       dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(0xa, 0)); /* Get DMA's dev
+       dma_dev = pci_get_bus_and_slot(priv->pdev->bus->number,
+                                      PCI_DEVFN(0xa, 0)); /* Get DMA's dev
                                                                information */
        /* Set Tx DMA */
        param = &priv->param_tx;
index afc6294..6edafb5 100644 (file)
@@ -1225,15 +1225,19 @@ static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
        .suspend = s3c24xx_serial_suspend,
        .resume = s3c24xx_serial_resume,
 };
+#define SERIAL_SAMSUNG_PM_OPS  (&s3c24xx_serial_pm_ops)
+
 #else /* !CONFIG_PM_SLEEP */
-#define s3c24xx_serial_pm_ops  NULL
+
+#define SERIAL_SAMSUNG_PM_OPS  NULL
 #endif /* CONFIG_PM_SLEEP */
 
 int s3c24xx_serial_init(struct platform_driver *drv,
                        struct s3c24xx_uart_info *info)
 {
        dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
-       drv->driver.pm = &s3c24xx_serial_pm_ops;
+
+       drv->driver.pm = SERIAL_SAMSUNG_PM_OPS;
 
        return platform_driver_register(drv);
 }
index db7912c..a3efbea 100644 (file)
@@ -200,6 +200,11 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in
                clear_bit(TTY_IO_ERROR, &tty->flags);
        }
 
+       /*
+        * This is to allow setserial on this port. People may want to set
+        * port/irq/type and then reconfigure the port properly if it failed
+        * now.
+        */
        if (retval && capable(CAP_SYS_ADMIN))
                retval = 0;
 
index 2ec57b2..5ea6ec3 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 
@@ -95,6 +96,12 @@ struct sci_port {
 #endif
 
        struct notifier_block           freq_transition;
+
+#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+       unsigned short saved_smr;
+       unsigned short saved_fcr;
+       unsigned char saved_brr;
+#endif
 };
 
 /* Function prototypes */
@@ -1076,7 +1083,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port)
        /* This routine is used for getting signals of: DTR, DCD, DSR, RI,
           and CTS/RTS */
 
-       return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR;
+       return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
 }
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -1633,11 +1640,25 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
        return ((freq + 16 * bps) / (32 * bps) - 1);
 }
 
+static void sci_reset(struct uart_port *port)
+{
+       unsigned int status;
+
+       do {
+               status = sci_in(port, SCxSR);
+       } while (!(status & SCxSR_TEND(port)));
+
+       sci_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
+
+       if (port->type != PORT_SCI)
+               sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
+}
+
 static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
                            struct ktermios *old)
 {
        struct sci_port *s = to_sci_port(port);
-       unsigned int status, baud, smr_val, max_baud;
+       unsigned int baud, smr_val, max_baud;
        int t = -1;
        u16 scfcr = 0;
 
@@ -1657,14 +1678,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
        sci_port_enable(s);
 
-       do {
-               status = sci_in(port, SCxSR);
-       } while (!(status & SCxSR_TEND(port)));
-
-       sci_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
-
-       if (port->type != PORT_SCI)
-               sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST);
+       sci_reset(port);
 
        smr_val = sci_in(port, SCSMR) & 3;
 
@@ -1913,6 +1927,7 @@ static int __devinit sci_init_single(struct platform_device *dev,
 
                port->dev = &dev->dev;
 
+               pm_runtime_irq_safe(&dev->dev);
                pm_runtime_enable(&dev->dev);
        }
 
@@ -2036,7 +2051,8 @@ static int __devinit serial_console_setup(struct console *co, char *options)
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
 
-       /* TODO: disable clock */
+       sci_port_disable(sci_port);
+
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
@@ -2079,6 +2095,36 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
        return 0;
 }
 
+#define uart_console(port)     ((port)->cons->index == (port)->line)
+
+static int sci_runtime_suspend(struct device *dev)
+{
+       struct sci_port *sci_port = dev_get_drvdata(dev);
+       struct uart_port *port = &sci_port->port;
+
+       if (uart_console(port)) {
+               sci_port->saved_smr = sci_in(port, SCSMR);
+               sci_port->saved_brr = sci_in(port, SCBRR);
+               sci_port->saved_fcr = sci_in(port, SCFCR);
+       }
+       return 0;
+}
+
+static int sci_runtime_resume(struct device *dev)
+{
+       struct sci_port *sci_port = dev_get_drvdata(dev);
+       struct uart_port *port = &sci_port->port;
+
+       if (uart_console(port)) {
+               sci_reset(port);
+               sci_out(port, SCSMR, sci_port->saved_smr);
+               sci_out(port, SCBRR, sci_port->saved_brr);
+               sci_out(port, SCFCR, sci_port->saved_fcr);
+               sci_out(port, SCSCR, sci_port->cfg->scscr);
+       }
+       return 0;
+}
+
 #define SCI_CONSOLE    (&serial_console)
 
 #else
@@ -2088,6 +2134,8 @@ static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
 }
 
 #define SCI_CONSOLE    NULL
+#define sci_runtime_suspend    NULL
+#define sci_runtime_resume     NULL
 
 #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
 
@@ -2203,6 +2251,8 @@ static int sci_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops sci_dev_pm_ops = {
+       .runtime_suspend = sci_runtime_suspend,
+       .runtime_resume = sci_runtime_resume,
        .suspend        = sci_suspend,
        .resume         = sci_resume,
 };
index c327218..9af9f08 100644 (file)
@@ -235,7 +235,7 @@ static inline void *qe2cpu_addr(dma_addr_t addr, struct uart_qe_port *qe_port)
                return qe_port->bd_virt + (addr - qe_port->bd_dma_addr);
 
        /* something nasty happened */
-       printk(KERN_ERR "%s: addr=%x\n", __func__, addr);
+       printk(KERN_ERR "%s: addr=%llx\n", __func__, (u64)addr);
        BUG();
        return NULL;
 }
index 150e4f7..4f1fc81 100644 (file)
@@ -1295,8 +1295,7 @@ static int tty_driver_install_tty(struct tty_driver *driver,
  *
  *     Locking: tty_mutex for now
  */
-static void tty_driver_remove_tty(struct tty_driver *driver,
-                                               struct tty_struct *tty)
+void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty)
 {
        if (driver->ops->remove)
                driver->ops->remove(driver, tty);
index 8669ba3..73cbbd8 100644 (file)
@@ -1775,6 +1775,8 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev,
                struct usb_interface *iface = usb_ifnum_to_if(udev,
                                cur_alt->desc.bInterfaceNumber);
 
+               if (!iface)
+                       return -EINVAL;
                if (iface->resetting_device) {
                        /*
                         * The USB core just reset the device, so the xHCI host
index 8f8d3f6..8f3eab1 100644 (file)
@@ -434,6 +434,7 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                            config_ep_by_speed(gadget, f, fp->out_ep)) {
                                fp->in_ep->desc = NULL;
                                fp->out_ep->desc = NULL;
+                               spin_unlock(&port->lock);
                                return -EINVAL;
                        }
                        usb_ep_enable(fp->out_ep);
index e051b30..4c32cb1 100644 (file)
@@ -343,7 +343,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
        u32                     temp;
        u32                     power_okay;
        int                     i;
-       u8                      resume_needed = 0;
+       unsigned long           resume_needed = 0;
 
        if (time_before (jiffies, ehci->next_statechange))
                msleep(5);
@@ -416,7 +416,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
                if (test_bit(i, &ehci->bus_suspended) &&
                                (temp & PORT_SUSPEND)) {
                        temp |= PORT_RESUME;
-                       resume_needed = 1;
+                       set_bit(i, &resume_needed);
                }
                ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
        }
@@ -431,8 +431,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
        i = HCS_N_PORTS (ehci->hcs_params);
        while (i--) {
                temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
-               if (test_bit(i, &ehci->bus_suspended) &&
-                               (temp & PORT_SUSPEND)) {
+               if (test_bit(i, &resume_needed)) {
                        temp &= ~(PORT_RWC_BITS | PORT_RESUME);
                        ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
                        ehci_vdbg (ehci, "resumed port %d\n", i + 1);
index b3958b3..9e77f1c 100644 (file)
@@ -86,6 +86,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
                goto fail_hcd;
        }
 
+       s5p_ehci->hcd = hcd;
        s5p_ehci->clk = clk_get(&pdev->dev, "usbhost");
 
        if (IS_ERR(s5p_ehci->clk)) {
index 0be788c..1e96d1f 100644 (file)
@@ -463,11 +463,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                        && (temp & PORT_POWER))
                                status |= USB_PORT_STAT_SUSPEND;
                }
-               if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
+               if ((temp & PORT_PLS_MASK) == XDEV_RESUME &&
+                               !DEV_SUPERSPEED(temp)) {
                        if ((temp & PORT_RESET) || !(temp & PORT_PE))
                                goto error;
-                       if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
-                                               bus_state->resume_done[wIndex])) {
+                       if (time_after_eq(jiffies,
+                                       bus_state->resume_done[wIndex])) {
                                xhci_dbg(xhci, "Resume USB2 port %d\n",
                                        wIndex + 1);
                                bus_state->resume_done[wIndex] = 0;
@@ -487,6 +488,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                xhci_ring_device(xhci, slot_id);
                                bus_state->port_c_suspend |= 1 << wIndex;
                                bus_state->suspended_ports &= ~(1 << wIndex);
+                       } else {
+                               /*
+                                * The resume has been signaling for less than
+                                * 20ms. Report the port status as SUSPEND,
+                                * let the usbcore check port status again
+                                * and clear resume signaling later.
+                                */
+                               status |= USB_PORT_STAT_SUSPEND;
                        }
                }
                if ((temp & PORT_PLS_MASK) == XDEV_U0
@@ -664,7 +673,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        xhci_dbg(xhci, "PORTSC %04x\n", temp);
                        if (temp & PORT_RESET)
                                goto error;
-                       if (temp & XDEV_U3) {
+                       if ((temp & PORT_PLS_MASK) == XDEV_U3) {
                                if ((temp & PORT_PE) == 0)
                                        goto error;
 
index 7113d16..54139a2 100644 (file)
@@ -514,8 +514,12 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
                        (unsigned long long) addr);
 }
 
+/* flip_cycle means flip the cycle bit of all but the first and last TRB.
+ * (The last TRB actually points to the ring enqueue pointer, which is not part
+ * of this TD.)  This is used to remove partially enqueued isoc TDs from a ring.
+ */
 static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
-               struct xhci_td *cur_td)
+               struct xhci_td *cur_td, bool flip_cycle)
 {
        struct xhci_segment *cur_seg;
        union xhci_trb *cur_trb;
@@ -528,6 +532,12 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
                         * leave the pointers intact.
                         */
                        cur_trb->generic.field[3] &= cpu_to_le32(~TRB_CHAIN);
+                       /* Flip the cycle bit (link TRBs can't be the first
+                        * or last TRB).
+                        */
+                       if (flip_cycle)
+                               cur_trb->generic.field[3] ^=
+                                       cpu_to_le32(TRB_CYCLE);
                        xhci_dbg(xhci, "Cancel (unchain) link TRB\n");
                        xhci_dbg(xhci, "Address = %p (0x%llx dma); "
                                        "in seg %p (0x%llx dma)\n",
@@ -541,6 +551,11 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
                        cur_trb->generic.field[2] = 0;
                        /* Preserve only the cycle bit of this TRB */
                        cur_trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
+                       /* Flip the cycle bit except on the first or last TRB */
+                       if (flip_cycle && cur_trb != cur_td->first_trb &&
+                                       cur_trb != cur_td->last_trb)
+                               cur_trb->generic.field[3] ^=
+                                       cpu_to_le32(TRB_CYCLE);
                        cur_trb->generic.field[3] |= cpu_to_le32(
                                TRB_TYPE(TRB_TR_NOOP));
                        xhci_dbg(xhci, "Cancel TRB %p (0x%llx dma) "
@@ -719,14 +734,14 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
                                        cur_td->urb->stream_id,
                                        cur_td, &deq_state);
                else
-                       td_to_noop(xhci, ep_ring, cur_td);
+                       td_to_noop(xhci, ep_ring, cur_td, false);
 remove_finished_td:
                /*
                 * The event handler won't see a completion for this TD anymore,
                 * so remove it from the endpoint ring's TD list.  Keep it in
                 * the cancelled TD list for URB completion later.
                 */
-               list_del(&cur_td->td_list);
+               list_del_init(&cur_td->td_list);
        }
        last_unlinked_td = cur_td;
        xhci_stop_watchdog_timer_in_irq(xhci, ep);
@@ -754,7 +769,7 @@ remove_finished_td:
        do {
                cur_td = list_entry(ep->cancelled_td_list.next,
                                struct xhci_td, cancelled_td_list);
-               list_del(&cur_td->cancelled_td_list);
+               list_del_init(&cur_td->cancelled_td_list);
 
                /* Clean up the cancelled URB */
                /* Doesn't matter what we pass for status, since the core will
@@ -862,9 +877,9 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
                                cur_td = list_first_entry(&ring->td_list,
                                                struct xhci_td,
                                                td_list);
-                               list_del(&cur_td->td_list);
+                               list_del_init(&cur_td->td_list);
                                if (!list_empty(&cur_td->cancelled_td_list))
-                                       list_del(&cur_td->cancelled_td_list);
+                                       list_del_init(&cur_td->cancelled_td_list);
                                xhci_giveback_urb_in_irq(xhci, cur_td,
                                                -ESHUTDOWN, "killed");
                        }
@@ -873,7 +888,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
                                                &temp_ep->cancelled_td_list,
                                                struct xhci_td,
                                                cancelled_td_list);
-                               list_del(&cur_td->cancelled_td_list);
+                               list_del_init(&cur_td->cancelled_td_list);
                                xhci_giveback_urb_in_irq(xhci, cur_td,
                                                -ESHUTDOWN, "killed");
                        }
@@ -1565,10 +1580,10 @@ td_cleanup:
                        else
                                *status = 0;
                }
-               list_del(&td->td_list);
+               list_del_init(&td->td_list);
                /* Was this TD slated to be cancelled but completed anyway? */
                if (!list_empty(&td->cancelled_td_list))
-                       list_del(&td->cancelled_td_list);
+                       list_del_init(&td->cancelled_td_list);
 
                urb_priv->td_cnt++;
                /* Giveback the urb when all the tds are completed */
@@ -2500,11 +2515,8 @@ static int prepare_transfer(struct xhci_hcd *xhci,
 
        if (td_index == 0) {
                ret = usb_hcd_link_urb_to_ep(bus_to_hcd(urb->dev->bus), urb);
-               if (unlikely(ret)) {
-                       xhci_urb_free_priv(xhci, urb_priv);
-                       urb->hcpriv = NULL;
+               if (unlikely(ret))
                        return ret;
-               }
        }
 
        td->urb = urb;
@@ -2672,6 +2684,10 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
 {
        int packets_transferred;
 
+       /* One TRB with a zero-length data packet. */
+       if (running_total == 0 && trb_buff_len == 0)
+               return 0;
+
        /* All the TRB queueing functions don't count the current TRB in
         * running_total.
         */
@@ -3113,20 +3129,15 @@ static int count_isoc_trbs_needed(struct xhci_hcd *xhci,
                struct urb *urb, int i)
 {
        int num_trbs = 0;
-       u64 addr, td_len, running_total;
+       u64 addr, td_len;
 
        addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset);
        td_len = urb->iso_frame_desc[i].length;
 
-       running_total = TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE - 1));
-       running_total &= TRB_MAX_BUFF_SIZE - 1;
-       if (running_total != 0)
-               num_trbs++;
-
-       while (running_total < td_len) {
+       num_trbs = DIV_ROUND_UP(td_len + (addr & (TRB_MAX_BUFF_SIZE - 1)),
+                       TRB_MAX_BUFF_SIZE);
+       if (num_trbs == 0)
                num_trbs++;
-               running_total += TRB_MAX_BUFF_SIZE;
-       }
 
        return num_trbs;
 }
@@ -3226,6 +3237,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        start_trb = &ep_ring->enqueue->generic;
        start_cycle = ep_ring->cycle_state;
 
+       urb_priv = urb->hcpriv;
        /* Queue the first TRB, even if it's zero-length */
        for (i = 0; i < num_tds; i++) {
                unsigned int total_packet_count;
@@ -3237,9 +3249,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                addr = start_addr + urb->iso_frame_desc[i].offset;
                td_len = urb->iso_frame_desc[i].length;
                td_remain_len = td_len;
-               /* FIXME: Ignoring zero-length packets, can those happen? */
                total_packet_count = roundup(td_len,
                                le16_to_cpu(urb->ep->desc.wMaxPacketSize));
+               /* A zero-length transfer still involves at least one packet. */
+               if (total_packet_count == 0)
+                       total_packet_count++;
                burst_count = xhci_get_burst_count(xhci, urb->dev, urb,
                                total_packet_count);
                residue = xhci_get_last_burst_packet_count(xhci,
@@ -3249,12 +3263,13 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
                ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
                                urb->stream_id, trbs_per_td, urb, i, mem_flags);
-               if (ret < 0)
-                       return ret;
+               if (ret < 0) {
+                       if (i == 0)
+                               return ret;
+                       goto cleanup;
+               }
 
-               urb_priv = urb->hcpriv;
                td = urb_priv->td[i];
-
                for (j = 0; j < trbs_per_td; j++) {
                        u32 remainder = 0;
                        field = TRB_TBC(burst_count) | TRB_TLBPC(residue);
@@ -3344,6 +3359,27 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
                        start_cycle, start_trb);
        return 0;
+cleanup:
+       /* Clean up a partially enqueued isoc transfer. */
+
+       for (i--; i >= 0; i--)
+               list_del_init(&urb_priv->td[i]->td_list);
+
+       /* Use the first TD as a temporary variable to turn the TDs we've queued
+        * into No-ops with a software-owned cycle bit. That way the hardware
+        * won't accidentally start executing bogus TDs when we partially
+        * overwrite them.  td->first_trb and td->start_seg are already set.
+        */
+       urb_priv->td[0]->last_trb = ep_ring->enqueue;
+       /* Every TRB except the first & last will have its cycle bit flipped. */
+       td_to_noop(xhci, ep_ring, urb_priv->td[0], true);
+
+       /* Reset the ring enqueue back to the first TRB and its cycle bit. */
+       ep_ring->enqueue = urb_priv->td[0]->first_trb;
+       ep_ring->enq_seg = urb_priv->td[0]->start_seg;
+       ep_ring->cycle_state = start_cycle;
+       usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
+       return ret;
 }
 
 /*
index 1c4432d..3a0f695 100644 (file)
@@ -1085,8 +1085,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
                if (urb->dev->speed == USB_SPEED_FULL) {
                        ret = xhci_check_maxpacket(xhci, slot_id,
                                        ep_index, urb);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               xhci_urb_free_priv(xhci, urb_priv);
+                               urb->hcpriv = NULL;
                                return ret;
+                       }
                }
 
                /* We have a spinlock and interrupts disabled, so we must pass
@@ -1097,6 +1100,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
                        goto dying;
                ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
                                slot_id, ep_index);
+               if (ret)
+                       goto free_priv;
                spin_unlock_irqrestore(&xhci->lock, flags);
        } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) {
                spin_lock_irqsave(&xhci->lock, flags);
@@ -1117,6 +1122,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
                        ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
                                        slot_id, ep_index);
                }
+               if (ret)
+                       goto free_priv;
                spin_unlock_irqrestore(&xhci->lock, flags);
        } else if (usb_endpoint_xfer_int(&urb->ep->desc)) {
                spin_lock_irqsave(&xhci->lock, flags);
@@ -1124,6 +1131,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
                        goto dying;
                ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
                                slot_id, ep_index);
+               if (ret)
+                       goto free_priv;
                spin_unlock_irqrestore(&xhci->lock, flags);
        } else {
                spin_lock_irqsave(&xhci->lock, flags);
@@ -1131,18 +1140,22 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
                        goto dying;
                ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb,
                                slot_id, ep_index);
+               if (ret)
+                       goto free_priv;
                spin_unlock_irqrestore(&xhci->lock, flags);
        }
 exit:
        return ret;
 dying:
-       xhci_urb_free_priv(xhci, urb_priv);
-       urb->hcpriv = NULL;
        xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for "
                        "non-responsive xHCI host.\n",
                        urb->ep->desc.bEndpointAddress, urb);
+       ret = -ESHUTDOWN;
+free_priv:
+       xhci_urb_free_priv(xhci, urb_priv);
+       urb->hcpriv = NULL;
        spin_unlock_irqrestore(&xhci->lock, flags);
-       return -ESHUTDOWN;
+       return ret;
 }
 
 /* Get the right ring for the given URB.
@@ -1239,6 +1252,13 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
        if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
                xhci_dbg(xhci, "HW died, freeing TD.\n");
                urb_priv = urb->hcpriv;
+               for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
+                       td = urb_priv->td[i];
+                       if (!list_empty(&td->td_list))
+                               list_del_init(&td->td_list);
+                       if (!list_empty(&td->cancelled_td_list))
+                               list_del_init(&td->cancelled_td_list);
+               }
 
                usb_hcd_unlink_urb_from_ep(hcd, urb);
                spin_unlock_irqrestore(&xhci->lock, flags);
index ae8c396..5e7cfba 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/prefetch.h>
 
 #include <asm/cacheflush.h>
 
index 149f3f3..318fb4e 100644 (file)
@@ -226,8 +226,10 @@ static int cppi_controller_stop(struct dma_controller *c)
        struct cppi             *controller;
        void __iomem            *tibase;
        int                     i;
+       struct musb             *musb;
 
        controller = container_of(c, struct cppi, controller);
+       musb = controller->musb;
 
        tibase = controller->tibase;
        /* DISABLE INDIVIDUAL CHANNEL Interrupts */
@@ -289,9 +291,11 @@ cppi_channel_allocate(struct dma_controller *c,
        u8                      index;
        struct cppi_channel     *cppi_ch;
        void __iomem            *tibase;
+       struct musb             *musb;
 
        controller = container_of(c, struct cppi, controller);
        tibase = controller->tibase;
+       musb = controller->musb;
 
        /* ep0 doesn't use DMA; remember cppi indices are 0..N-1 */
        index = ep->epnum - 1;
@@ -339,7 +343,8 @@ static void cppi_channel_release(struct dma_channel *channel)
        c = container_of(channel, struct cppi_channel, channel);
        tibase = c->controller->tibase;
        if (!c->hw_ep)
-               dev_dbg(musb->controller, "releasing idle DMA channel %p\n", c);
+               dev_dbg(c->controller->musb->controller,
+                       "releasing idle DMA channel %p\n", c);
        else if (!c->transmit)
                core_rxirq_enable(tibase, c->index + 1);
 
@@ -357,10 +362,11 @@ cppi_dump_rx(int level, struct cppi_channel *c, const char *tag)
 
        musb_ep_select(base, c->index + 1);
 
-       DBG(level, "RX DMA%d%s: %d left, csr %04x, "
-                       "%08x H%08x S%08x C%08x, "
-                       "B%08x L%08x %08x .. %08x"
-                       "\n",
+       dev_dbg(c->controller->musb->controller,
+               "RX DMA%d%s: %d left, csr %04x, "
+               "%08x H%08x S%08x C%08x, "
+               "B%08x L%08x %08x .. %08x"
+               "\n",
                c->index, tag,
                musb_readl(c->controller->tibase,
                        DAVINCI_RXCPPI_BUFCNT0_REG + 4 * c->index),
@@ -387,10 +393,11 @@ cppi_dump_tx(int level, struct cppi_channel *c, const char *tag)
 
        musb_ep_select(base, c->index + 1);
 
-       DBG(level, "TX DMA%d%s: csr %04x, "
-                       "H%08x S%08x C%08x %08x, "
-                       "F%08x L%08x .. %08x"
-                       "\n",
+       dev_dbg(c->controller->musb->controller,
+               "TX DMA%d%s: csr %04x, "
+               "H%08x S%08x C%08x %08x, "
+               "F%08x L%08x .. %08x"
+               "\n",
                c->index, tag,
                musb_readw(c->hw_ep->regs, MUSB_TXCSR),
 
@@ -1022,6 +1029,7 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
        int                             i;
        dma_addr_t                      safe2ack;
        void __iomem                    *regs = rx->hw_ep->regs;
+       struct musb                     *musb = cppi->musb;
 
        cppi_dump_rx(6, rx, "/K");
 
index 668eeef..b3c065a 100644 (file)
@@ -172,7 +172,8 @@ enum musb_g_ep0_state {
 #endif
 
 /* TUSB mapping: "flat" plus ep0 special cases */
-#if    defined(CONFIG_USB_MUSB_TUSB6010)
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+       defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
 #define musb_ep_select(_mbase, _epnum) \
        musb_writeb((_mbase), MUSB_INDEX, (_epnum))
 #define        MUSB_EP_OFFSET                  MUSB_TUSB_OFFSET
@@ -241,7 +242,8 @@ struct musb_hw_ep {
        void __iomem            *fifo;
        void __iomem            *regs;
 
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+       defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
        void __iomem            *conf;
 #endif
 
@@ -258,7 +260,8 @@ struct musb_hw_ep {
        struct dma_channel      *tx_channel;
        struct dma_channel      *rx_channel;
 
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+       defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
        /* TUSB has "asynchronous" and "synchronous" dma modes */
        dma_addr_t              fifo_async;
        dma_addr_t              fifo_sync;
@@ -356,7 +359,8 @@ struct musb {
        void __iomem            *ctrl_base;
        void __iomem            *mregs;
 
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+       defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
        dma_addr_t              async;
        dma_addr_t              sync;
        void __iomem            *sync_va;
index 8c41a2e..e818203 100644 (file)
@@ -1856,6 +1856,7 @@ int __init musb_gadget_setup(struct musb *musb)
 
        return 0;
 err:
+       musb->g.dev.parent = NULL;
        device_unregister(&musb->g.dev);
        return status;
 }
@@ -1863,7 +1864,8 @@ err:
 void musb_gadget_cleanup(struct musb *musb)
 {
        usb_del_gadget_udc(&musb->g);
-       device_unregister(&musb->g.dev);
+       if (musb->g.dev.parent)
+               device_unregister(&musb->g.dev);
 }
 
 /*
index 8241070..03f2655 100644 (file)
 #define MUSB_TESTMODE          0x0F    /* 8 bit */
 
 /* Get offset for a given FIFO from musb->mregs */
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) ||       \
+       defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
 #define MUSB_FIFO_OFFSET(epnum)        (0x200 + ((epnum) * 0x20))
 #else
 #define MUSB_FIFO_OFFSET(epnum)        (0x20 + ((epnum) * 4))
 #define MUSB_FLAT_OFFSET(_epnum, _offset)      \
        (0x100 + (0x10*(_epnum)) + (_offset))
 
-#ifdef CONFIG_USB_MUSB_TUSB6010
+#if defined(CONFIG_USB_MUSB_TUSB6010) ||       \
+       defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
 /* TUSB6010 EP0 configuration register is special */
 #define MUSB_TUSB_OFFSET(_epnum, _offset)      \
        (0x10 + _offset)
index 9eec41f..ec14801 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/prefetch.h>
 #include <linux/usb.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
index 07c8a73..b67b4bc 100644 (file)
@@ -20,6 +20,7 @@
 #include <plat/mux.h>
 
 #include "musb_core.h"
+#include "tusb6010.h"
 
 #define to_chdat(c)            ((struct tusb_omap_dma_ch *)(c)->private_data)
 
index cecace4..ef4333f 100644 (file)
@@ -65,7 +65,8 @@ static void ux500_tx_work(struct work_struct *data)
        struct musb *musb = hw_ep->musb;
        unsigned long flags;
 
-       DBG(4, "DMA tx transfer done on hw_ep=%d\n", hw_ep->epnum);
+       dev_dbg(musb->controller, "DMA tx transfer done on hw_ep=%d\n",
+               hw_ep->epnum);
 
        spin_lock_irqsave(&musb->lock, flags);
        ux500_channel->channel.actual_len = ux500_channel->cur_len;
@@ -84,7 +85,8 @@ static void ux500_rx_work(struct work_struct *data)
        struct musb *musb = hw_ep->musb;
        unsigned long flags;
 
-       DBG(4, "DMA rx transfer done on hw_ep=%d\n", hw_ep->epnum);
+       dev_dbg(musb->controller, "DMA rx transfer done on hw_ep=%d\n",
+               hw_ep->epnum);
 
        spin_lock_irqsave(&musb->lock, flags);
        ux500_channel->channel.actual_len = ux500_channel->cur_len;
@@ -116,9 +118,11 @@ static bool ux500_configure_channel(struct dma_channel *channel,
        enum dma_slave_buswidth addr_width;
        dma_addr_t usb_fifo_addr = (MUSB_FIFO_OFFSET(hw_ep->epnum) +
                                        ux500_channel->controller->phy_base);
+       struct musb *musb = ux500_channel->controller->private_data;
 
-       DBG(4, "packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n",
-                       packet_sz, mode, dma_addr, len, ux500_channel->is_tx);
+       dev_dbg(musb->controller,
+               "packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n",
+               packet_sz, mode, dma_addr, len, ux500_channel->is_tx);
 
        ux500_channel->cur_len = len;
 
@@ -133,15 +137,13 @@ static bool ux500_configure_channel(struct dma_channel *channel,
                                        DMA_SLAVE_BUSWIDTH_4_BYTES;
 
        slave_conf.direction = direction;
-       if (direction == DMA_FROM_DEVICE) {
-               slave_conf.src_addr = usb_fifo_addr;
-               slave_conf.src_addr_width = addr_width;
-               slave_conf.src_maxburst = 16;
-       } else {
-               slave_conf.dst_addr = usb_fifo_addr;
-               slave_conf.dst_addr_width = addr_width;
-               slave_conf.dst_maxburst = 16;
-       }
+       slave_conf.src_addr = usb_fifo_addr;
+       slave_conf.src_addr_width = addr_width;
+       slave_conf.src_maxburst = 16;
+       slave_conf.dst_addr = usb_fifo_addr;
+       slave_conf.dst_addr_width = addr_width;
+       slave_conf.dst_maxburst = 16;
+
        dma_chan->device->device_control(dma_chan, DMA_SLAVE_CONFIG,
                                             (unsigned long) &slave_conf);
 
@@ -166,6 +168,7 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,
        struct ux500_dma_controller *controller = container_of(c,
                        struct ux500_dma_controller, controller);
        struct ux500_dma_channel *ux500_channel = NULL;
+       struct musb *musb = controller->private_data;
        u8 ch_num = hw_ep->epnum - 1;
        u32 max_ch;
 
@@ -192,7 +195,7 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,
        ux500_channel->hw_ep = hw_ep;
        ux500_channel->is_allocated = 1;
 
-       DBG(7, "hw_ep=%d, is_tx=0x%x, channel=%d\n",
+       dev_dbg(musb->controller, "hw_ep=%d, is_tx=0x%x, channel=%d\n",
                hw_ep->epnum, is_tx, ch_num);
 
        return &(ux500_channel->channel);
@@ -201,8 +204,9 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,
 static void ux500_dma_channel_release(struct dma_channel *channel)
 {
        struct ux500_dma_channel *ux500_channel = channel->private_data;
+       struct musb *musb = ux500_channel->controller->private_data;
 
-       DBG(7, "channel=%d\n", ux500_channel->ch_num);
+       dev_dbg(musb->controller, "channel=%d\n", ux500_channel->ch_num);
 
        if (ux500_channel->is_allocated) {
                ux500_channel->is_allocated = 0;
@@ -252,8 +256,8 @@ static int ux500_dma_channel_abort(struct dma_channel *channel)
        void __iomem *epio = musb->endpoints[ux500_channel->hw_ep->epnum].regs;
        u16 csr;
 
-       DBG(4, "channel=%d, is_tx=%d\n", ux500_channel->ch_num,
-                                               ux500_channel->is_tx);
+       dev_dbg(musb->controller, "channel=%d, is_tx=%d\n",
+               ux500_channel->ch_num, ux500_channel->is_tx);
 
        if (channel->status == MUSB_DMA_STATUS_BUSY) {
                if (ux500_channel->is_tx) {
index 78a2cf9..5fc13e7 100644 (file)
@@ -101,6 +101,7 @@ static int   ftdi_jtag_probe(struct usb_serial *serial);
 static int   ftdi_mtxorb_hack_setup(struct usb_serial *serial);
 static int   ftdi_NDI_device_setup(struct usb_serial *serial);
 static int   ftdi_stmclite_probe(struct usb_serial *serial);
+static int   ftdi_8u2232c_probe(struct usb_serial *serial);
 static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);
 static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
 
@@ -128,6 +129,10 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
        .probe  = ftdi_stmclite_probe,
 };
 
+static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
+       .probe  = ftdi_8u2232c_probe,
+};
+
 /*
  * The 8U232AM has the same API as the sio except for:
  * - it can support MUCH higher baudrates; up to:
@@ -178,7 +183,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) ,
+               .driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
@@ -1737,6 +1743,18 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
        return 0;
 }
 
+static int ftdi_8u2232c_probe(struct usb_serial *serial)
+{
+       struct usb_device *udev = serial->dev;
+
+       dbg("%s", __func__);
+
+       if (strcmp(udev->manufacturer, "CALAO Systems") == 0)
+               return ftdi_jtag_probe(serial);
+
+       return 0;
+}
+
 /*
  * First and second port on STMCLiteadaptors is reserved for JTAG interface
  * and the forth port for pio
index 8156561..fe22e90 100644 (file)
@@ -148,6 +148,8 @@ static void option_instat_callback(struct urb *urb);
 #define HUAWEI_PRODUCT_K4505                   0x1464
 #define HUAWEI_PRODUCT_K3765                   0x1465
 #define HUAWEI_PRODUCT_E14AC                   0x14AC
+#define HUAWEI_PRODUCT_K3806                   0x14AE
+#define HUAWEI_PRODUCT_K4605                   0x14C6
 #define HUAWEI_PRODUCT_K3770                   0x14C9
 #define HUAWEI_PRODUCT_K3771                   0x14CA
 #define HUAWEI_PRODUCT_K4510                   0x14CB
@@ -416,6 +418,56 @@ static void option_instat_callback(struct urb *urb);
 #define SAMSUNG_VENDOR_ID                       0x04e8
 #define SAMSUNG_PRODUCT_GT_B3730                0x6889
 
+/* YUGA products  www.yuga-info.com*/
+#define YUGA_VENDOR_ID                         0x257A
+#define YUGA_PRODUCT_CEM600                    0x1601
+#define YUGA_PRODUCT_CEM610                    0x1602
+#define YUGA_PRODUCT_CEM500                    0x1603
+#define YUGA_PRODUCT_CEM510                    0x1604
+#define YUGA_PRODUCT_CEM800                    0x1605
+#define YUGA_PRODUCT_CEM900                    0x1606
+
+#define YUGA_PRODUCT_CEU818                    0x1607
+#define YUGA_PRODUCT_CEU816                    0x1608
+#define YUGA_PRODUCT_CEU828                    0x1609
+#define YUGA_PRODUCT_CEU826                    0x160A
+#define YUGA_PRODUCT_CEU518                    0x160B
+#define YUGA_PRODUCT_CEU516                    0x160C
+#define YUGA_PRODUCT_CEU528                    0x160D
+#define YUGA_PRODUCT_CEU526                    0x160F
+
+#define YUGA_PRODUCT_CWM600                    0x2601
+#define YUGA_PRODUCT_CWM610                    0x2602
+#define YUGA_PRODUCT_CWM500                    0x2603
+#define YUGA_PRODUCT_CWM510                    0x2604
+#define YUGA_PRODUCT_CWM800                    0x2605
+#define YUGA_PRODUCT_CWM900                    0x2606
+
+#define YUGA_PRODUCT_CWU718                    0x2607
+#define YUGA_PRODUCT_CWU716                    0x2608
+#define YUGA_PRODUCT_CWU728                    0x2609
+#define YUGA_PRODUCT_CWU726                    0x260A
+#define YUGA_PRODUCT_CWU518                    0x260B
+#define YUGA_PRODUCT_CWU516                    0x260C
+#define YUGA_PRODUCT_CWU528                    0x260D
+#define YUGA_PRODUCT_CWU526                    0x260F
+
+#define YUGA_PRODUCT_CLM600                    0x2601
+#define YUGA_PRODUCT_CLM610                    0x2602
+#define YUGA_PRODUCT_CLM500                    0x2603
+#define YUGA_PRODUCT_CLM510                    0x2604
+#define YUGA_PRODUCT_CLM800                    0x2605
+#define YUGA_PRODUCT_CLM900                    0x2606
+
+#define YUGA_PRODUCT_CLU718                    0x2607
+#define YUGA_PRODUCT_CLU716                    0x2608
+#define YUGA_PRODUCT_CLU728                    0x2609
+#define YUGA_PRODUCT_CLU726                    0x260A
+#define YUGA_PRODUCT_CLU518                    0x260B
+#define YUGA_PRODUCT_CLU516                    0x260C
+#define YUGA_PRODUCT_CLU528                    0x260D
+#define YUGA_PRODUCT_CLU526                    0x260F
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -551,6 +603,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
@@ -1005,6 +1059,48 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
        { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
        { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM500) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM510) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM800) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM900) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU818) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU816) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU828) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU826) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU518) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU516) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU528) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU526) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM600) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM610) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM500) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM510) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM800) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM900) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU718) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU716) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU728) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU726) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU518) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU516) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU528) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU526) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM600) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM610) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM500) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM510) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM800) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM900) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU718) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU716) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU728) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU726) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU518) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },
+       { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1134,11 +1230,13 @@ static int option_probe(struct usb_serial *serial,
                serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)
                return -ENODEV;
 
-       /* Don't bind network interfaces on Huawei K3765 & K4505 */
+       /* Don't bind network interfaces on Huawei K3765, K4505 & K4605 */
        if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID &&
                (serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 ||
-                       serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) &&
-               serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
+                       serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505 ||
+                       serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4605) &&
+               (serial->interface->cur_altsetting->desc.bInterfaceNumber == 1 ||
+                       serial->interface->cur_altsetting->desc.bInterfaceNumber == 2))
                return -ENODEV;
 
        /* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
index 05a8832..d06886a 100644 (file)
@@ -1009,4 +1009,4 @@ module_exit(adp8870_exit);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("ADP8870 Backlight driver");
-MODULE_ALIAS("platform:adp8870-backlight");
+MODULE_ALIAS("i2c:adp8870-backlight");
index 80d292f..7363c1b 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/backlight.h>
 #endif
 
-static const char const *backlight_types[] = {
+static const char *const backlight_types[] = {
        [BACKLIGHT_RAW] = "raw",
        [BACKLIGHT_PLATFORM] = "platform",
        [BACKLIGHT_FIRMWARE] = "firmware",
index 9f1e389..b058291 100644 (file)
@@ -11,7 +11,7 @@
  * BRIGHT, on the Cirrus EP9307, EP9312, and EP9315 processors.
  */
 
-
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/fb.h>
index b8f38ec..8b5b2a4 100644 (file)
@@ -28,6 +28,8 @@ struct pwm_bl_data {
        unsigned int            lth_brightness;
        int                     (*notify)(struct device *,
                                          int brightness);
+       void                    (*notify_after)(struct device *,
+                                       int brightness);
        int                     (*check_fb)(struct device *, struct fb_info *);
 };
 
@@ -55,6 +57,10 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
                pwm_config(pb->pwm, brightness, pb->period);
                pwm_enable(pb->pwm);
        }
+
+       if (pb->notify_after)
+               pb->notify_after(pb->dev, brightness);
+
        return 0;
 }
 
@@ -105,6 +111,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 
        pb->period = data->pwm_period_ns;
        pb->notify = data->notify;
+       pb->notify_after = data->notify_after;
        pb->check_fb = data->check_fb;
        pb->lth_brightness = data->lth_brightness *
                (data->pwm_period_ns / data->max_brightness);
@@ -172,6 +179,8 @@ static int pwm_backlight_suspend(struct platform_device *pdev,
                pb->notify(pb->dev, 0);
        pwm_config(pb->pwm, 0, pb->period);
        pwm_disable(pb->pwm);
+       if (pb->notify_after)
+               pb->notify_after(pb->dev, 0);
        return 0;
 }
 
index 02bf7bf..b5abaae 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     dscore.c
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -1024,5 +1024,5 @@ module_init(ds_init);
 module_exit(ds_fini);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)");
index 334d1cc..f667c26 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     matrox_w1.c
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -39,7 +39,7 @@
 #include "../w1_log.h"
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire prtocol) over VGA DDC(matrox gpio).");
 
 static struct pci_device_id matrox_w1_tbl[] = {
index c377818..7c8cdb8 100644 (file)
@@ -373,7 +373,7 @@ static int w1_f29_add_slave(struct w1_slave *sl)
 static void w1_f29_remove_slave(struct w1_slave *sl)
 {
        int i;
-       for (i = NB_SYSFS_BIN_FILES; i <= 0; --i)
+       for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
                sysfs_remove_bin_file(&sl->dev.kobj,
                        &(w1_f29_sysfs_bin_files[i]));
 }
index cc8c02e..8465562 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1_smem.c
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -32,7 +32,7 @@
 #include "../w1_family.h"
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
 
 static struct w1_family w1_smem_family_01 = {
index 402928b..a1ef9b5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1_therm.c
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
 #include "../w1_family.h"
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
 
 /* Allow the strong pullup to be disabled, but default to enabled.
index 6c136c1..c374978 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1.c
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -42,7 +42,7 @@
 #include "w1_netlink.h"
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
 
 static int w1_timeout = 10;
index 1ce23fc..4d012ca 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1.h
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 4a09904..6335979 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1_family.c
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 98a1ac0..490cda2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1_family.h
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index b50be3f..d220bce 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1_int.c
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 4274082..2ad7d44 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1_int.h
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 8e8b64c..765b37b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1_io.c
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index e6ab7cf..9c7bd62 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     w1_log.h
  *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 55aabd9..40788c9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * w1_netlink.c
  *
- * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2003 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 27e950f..b0922dc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * w1_netlink.h
  *
- * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2003 Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 1b4afd8..6ea852e 100644 (file)
@@ -70,6 +70,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
+#include <linux/module.h>
 #include <linux/workqueue.h>
 #include <xen/balloon.h>
 #include <xen/tmem.h>
index 46ce357..410ffd6 100644 (file)
@@ -54,9 +54,9 @@ extern struct kmem_cache *v9fs_inode_cache;
 
 struct inode *v9fs_alloc_inode(struct super_block *sb);
 void v9fs_destroy_inode(struct inode *inode);
-struct inode *v9fs_get_inode(struct super_block *sb, int mode);
+struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t);
 int v9fs_init_inode(struct v9fs_session_info *v9ses,
-                   struct inode *inode, int mode);
+                   struct inode *inode, int mode, dev_t);
 void v9fs_evict_inode(struct inode *inode);
 ino_t v9fs_qid2ino(struct p9_qid *qid);
 void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
@@ -83,4 +83,6 @@ static inline void v9fs_invalidate_inode_attr(struct inode *inode)
        v9inode->cache_validity |= V9FS_INO_INVALID_ATTR;
        return;
 }
+
+int v9fs_open_to_dotl_flags(int flags);
 #endif
index 3c173fc..62857a8 100644 (file)
@@ -65,7 +65,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
        v9inode = V9FS_I(inode);
        v9ses = v9fs_inode2v9ses(inode);
        if (v9fs_proto_dotl(v9ses))
-               omode = file->f_flags;
+               omode = v9fs_open_to_dotl_flags(file->f_flags);
        else
                omode = v9fs_uflags2omode(file->f_flags,
                                        v9fs_proto_dotu(v9ses));
@@ -169,7 +169,18 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
 
        /* convert posix lock to p9 tlock args */
        memset(&flock, 0, sizeof(flock));
-       flock.type = fl->fl_type;
+       /* map the lock type */
+       switch (fl->fl_type) {
+       case F_RDLCK:
+               flock.type = P9_LOCK_TYPE_RDLCK;
+               break;
+       case F_WRLCK:
+               flock.type = P9_LOCK_TYPE_WRLCK;
+               break;
+       case F_UNLCK:
+               flock.type = P9_LOCK_TYPE_UNLCK;
+               break;
+       }
        flock.start = fl->fl_start;
        if (fl->fl_end == OFFSET_MAX)
                flock.length = 0;
@@ -245,7 +256,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
 
        /* convert posix lock to p9 tgetlock args */
        memset(&glock, 0, sizeof(glock));
-       glock.type = fl->fl_type;
+       glock.type  = P9_LOCK_TYPE_UNLCK;
        glock.start = fl->fl_start;
        if (fl->fl_end == OFFSET_MAX)
                glock.length = 0;
@@ -257,17 +268,26 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
        res = p9_client_getlock_dotl(fid, &glock);
        if (res < 0)
                return res;
-       if (glock.type != F_UNLCK) {
-               fl->fl_type = glock.type;
+       /* map 9p lock type to os lock type */
+       switch (glock.type) {
+       case P9_LOCK_TYPE_RDLCK:
+               fl->fl_type = F_RDLCK;
+               break;
+       case P9_LOCK_TYPE_WRLCK:
+               fl->fl_type = F_WRLCK;
+               break;
+       case P9_LOCK_TYPE_UNLCK:
+               fl->fl_type = F_UNLCK;
+               break;
+       }
+       if (glock.type != P9_LOCK_TYPE_UNLCK) {
                fl->fl_start = glock.start;
                if (glock.length == 0)
                        fl->fl_end = OFFSET_MAX;
                else
                        fl->fl_end = glock.start + glock.length - 1;
                fl->fl_pid = glock.proc_id;
-       } else
-               fl->fl_type = F_UNLCK;
-
+       }
        return res;
 }
 
index 8bb5507..e3c03db 100644 (file)
@@ -95,15 +95,18 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
 /**
  * p9mode2unixmode- convert plan9 mode bits to unix mode bits
  * @v9ses: v9fs session information
- * @mode: mode to convert
+ * @stat: p9_wstat from which mode need to be derived
+ * @rdev: major number, minor number in case of device files.
  *
  */
-
-static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
+static int p9mode2unixmode(struct v9fs_session_info *v9ses,
+                          struct p9_wstat *stat, dev_t *rdev)
 {
        int res;
+       int mode = stat->mode;
 
-       res = mode & 0777;
+       res = mode & S_IALLUGO;
+       *rdev = 0;
 
        if ((mode & P9_DMDIR) == P9_DMDIR)
                res |= S_IFDIR;
@@ -116,9 +119,26 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
                 && (v9ses->nodev == 0))
                res |= S_IFIFO;
        else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
-                && (v9ses->nodev == 0))
-               res |= S_IFBLK;
-       else
+                && (v9ses->nodev == 0)) {
+               char type = 0, ext[32];
+               int major = -1, minor = -1;
+
+               strncpy(ext, stat->extension, sizeof(ext));
+               sscanf(ext, "%c %u %u", &type, &major, &minor);
+               switch (type) {
+               case 'c':
+                       res |= S_IFCHR;
+                       break;
+               case 'b':
+                       res |= S_IFBLK;
+                       break;
+               default:
+                       P9_DPRINTK(P9_DEBUG_ERROR,
+                               "Unknown special type %c %s\n", type,
+                               stat->extension);
+               };
+               *rdev = MKDEV(major, minor);
+       } else
                res |= S_IFREG;
 
        if (v9fs_proto_dotu(v9ses)) {
@@ -131,7 +151,6 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
                if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
                        res |= S_ISVTX;
        }
-
        return res;
 }
 
@@ -242,13 +261,13 @@ void v9fs_destroy_inode(struct inode *inode)
 }
 
 int v9fs_init_inode(struct v9fs_session_info *v9ses,
-                   struct inode *inode, int mode)
+                   struct inode *inode, int mode, dev_t rdev)
 {
        int err = 0;
 
        inode_init_owner(inode, NULL, mode);
        inode->i_blocks = 0;
-       inode->i_rdev = 0;
+       inode->i_rdev = rdev;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        inode->i_mapping->a_ops = &v9fs_addr_operations;
 
@@ -335,7 +354,7 @@ error:
  *
  */
 
-struct inode *v9fs_get_inode(struct super_block *sb, int mode)
+struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t rdev)
 {
        int err;
        struct inode *inode;
@@ -348,7 +367,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
                P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
                return ERR_PTR(-ENOMEM);
        }
-       err = v9fs_init_inode(v9ses, inode, mode);
+       err = v9fs_init_inode(v9ses, inode, mode, rdev);
        if (err) {
                iput(inode);
                return ERR_PTR(err);
@@ -435,11 +454,12 @@ void v9fs_evict_inode(struct inode *inode)
 static int v9fs_test_inode(struct inode *inode, void *data)
 {
        int umode;
+       dev_t rdev;
        struct v9fs_inode *v9inode = V9FS_I(inode);
        struct p9_wstat *st = (struct p9_wstat *)data;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
 
-       umode = p9mode2unixmode(v9ses, st->mode);
+       umode = p9mode2unixmode(v9ses, st, &rdev);
        /* don't match inode of different type */
        if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
                return 0;
@@ -473,6 +493,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
                                   struct p9_wstat *st,
                                   int new)
 {
+       dev_t rdev;
        int retval, umode;
        unsigned long i_ino;
        struct inode *inode;
@@ -496,8 +517,8 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
         * later.
         */
        inode->i_ino = i_ino;
-       umode = p9mode2unixmode(v9ses, st->mode);
-       retval = v9fs_init_inode(v9ses, inode, umode);
+       umode = p9mode2unixmode(v9ses, st, &rdev);
+       retval = v9fs_init_inode(v9ses, inode, umode, rdev);
        if (retval)
                goto error;
 
@@ -531,6 +552,19 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
        return inode;
 }
 
+/**
+ * v9fs_at_to_dotl_flags- convert Linux specific AT flags to
+ * plan 9 AT flag.
+ * @flags: flags to convert
+ */
+static int v9fs_at_to_dotl_flags(int flags)
+{
+       int rflags = 0;
+       if (flags & AT_REMOVEDIR)
+               rflags |= P9_DOTL_AT_REMOVEDIR;
+       return rflags;
+}
+
 /**
  * v9fs_remove - helper function to remove files and directories
  * @dir: directory inode that is being deleted
@@ -558,7 +592,8 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
                return retval;
        }
        if (v9fs_proto_dotl(v9ses))
-               retval = p9_client_unlinkat(dfid, dentry->d_name.name, flags);
+               retval = p9_client_unlinkat(dfid, dentry->d_name.name,
+                                           v9fs_at_to_dotl_flags(flags));
        if (retval == -EOPNOTSUPP) {
                /* Try the one based on path */
                v9fid = v9fs_fid_clone(dentry);
@@ -645,13 +680,11 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
                P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
                goto error;
        }
-       d_instantiate(dentry, inode);
        err = v9fs_fid_add(dentry, fid);
        if (err < 0)
                goto error;
-
+       d_instantiate(dentry, inode);
        return ofid;
-
 error:
        if (ofid)
                p9_client_clunk(ofid);
@@ -792,6 +825,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
                                      struct nameidata *nameidata)
 {
+       struct dentry *res;
        struct super_block *sb;
        struct v9fs_session_info *v9ses;
        struct p9_fid *dfid, *fid;
@@ -823,22 +857,35 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 
                return ERR_PTR(result);
        }
-
-       inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+       /*
+        * Make sure we don't use a wrong inode due to parallel
+        * unlink. For cached mode create calls request for new
+        * inode. But with cache disabled, lookup should do this.
+        */
+       if (v9ses->cache)
+               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+       else
+               inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
        if (IS_ERR(inode)) {
                result = PTR_ERR(inode);
                inode = NULL;
                goto error;
        }
-
        result = v9fs_fid_add(dentry, fid);
        if (result < 0)
                goto error_iput;
-
 inst_out:
-       d_add(dentry, inode);
-       return NULL;
-
+       /*
+        * If we had a rename on the server and a parallel lookup
+        * for the new name, then make sure we instantiate with
+        * the new name. ie look up for a/b, while on server somebody
+        * moved b under k and client parallely did a lookup for
+        * k/b.
+        */
+       res = d_materialise_unique(dentry, inode);
+       if (!IS_ERR(res))
+               return res;
+       result = PTR_ERR(res);
 error_iput:
        iput(inode);
 error:
@@ -1002,7 +1049,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
                return PTR_ERR(st);
 
        v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
-               generic_fillattr(dentry->d_inode, stat);
+       generic_fillattr(dentry->d_inode, stat);
 
        p9stat_free(st);
        kfree(st);
@@ -1086,6 +1133,7 @@ void
 v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
        struct super_block *sb)
 {
+       mode_t mode;
        char ext[32];
        char tag_name[14];
        unsigned int i_nlink;
@@ -1121,31 +1169,9 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
                                inode->i_nlink = i_nlink;
                }
        }
-       inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
-       if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
-               char type = 0;
-               int major = -1;
-               int minor = -1;
-
-               strncpy(ext, stat->extension, sizeof(ext));
-               sscanf(ext, "%c %u %u", &type, &major, &minor);
-               switch (type) {
-               case 'c':
-                       inode->i_mode &= ~S_IFBLK;
-                       inode->i_mode |= S_IFCHR;
-                       break;
-               case 'b':
-                       break;
-               default:
-                       P9_DPRINTK(P9_DEBUG_ERROR,
-                               "Unknown special type %c %s\n", type,
-                               stat->extension);
-               };
-               inode->i_rdev = MKDEV(major, minor);
-               init_special_inode(inode, inode->i_mode, inode->i_rdev);
-       } else
-               inode->i_rdev = 0;
-
+       mode = stat->mode & S_IALLUGO;
+       mode |= inode->i_mode & ~S_IALLUGO;
+       inode->i_mode = mode;
        i_size_write(inode, stat->length);
 
        /* not real number of blocks, but 512 byte ones ... */
@@ -1411,6 +1437,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 
 int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
 {
+       int umode;
+       dev_t rdev;
        loff_t i_size;
        struct p9_wstat *st;
        struct v9fs_session_info *v9ses;
@@ -1419,6 +1447,12 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
        st = p9_client_stat(fid);
        if (IS_ERR(st))
                return PTR_ERR(st);
+       /*
+        * Don't update inode if the file type is different
+        */
+       umode = p9mode2unixmode(v9ses, st, &rdev);
+       if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
+               goto out;
 
        spin_lock(&inode->i_lock);
        /*
@@ -1430,6 +1464,7 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
        if (v9ses->cache)
                inode->i_size = i_size;
        spin_unlock(&inode->i_lock);
+out:
        p9stat_free(st);
        kfree(st);
        return 0;
index b6c8ed2..aded79f 100644 (file)
@@ -153,7 +153,8 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
         * later.
         */
        inode->i_ino = i_ino;
-       retval = v9fs_init_inode(v9ses, inode, st->st_mode);
+       retval = v9fs_init_inode(v9ses, inode,
+                                st->st_mode, new_decode_dev(st->st_rdev));
        if (retval)
                goto error;
 
@@ -190,6 +191,58 @@ v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
        return inode;
 }
 
+struct dotl_openflag_map {
+       int open_flag;
+       int dotl_flag;
+};
+
+static int v9fs_mapped_dotl_flags(int flags)
+{
+       int i;
+       int rflags = 0;
+       struct dotl_openflag_map dotl_oflag_map[] = {
+               { O_CREAT,      P9_DOTL_CREATE },
+               { O_EXCL,       P9_DOTL_EXCL },
+               { O_NOCTTY,     P9_DOTL_NOCTTY },
+               { O_TRUNC,      P9_DOTL_TRUNC },
+               { O_APPEND,     P9_DOTL_APPEND },
+               { O_NONBLOCK,   P9_DOTL_NONBLOCK },
+               { O_DSYNC,      P9_DOTL_DSYNC },
+               { FASYNC,       P9_DOTL_FASYNC },
+               { O_DIRECT,     P9_DOTL_DIRECT },
+               { O_LARGEFILE,  P9_DOTL_LARGEFILE },
+               { O_DIRECTORY,  P9_DOTL_DIRECTORY },
+               { O_NOFOLLOW,   P9_DOTL_NOFOLLOW },
+               { O_NOATIME,    P9_DOTL_NOATIME },
+               { O_CLOEXEC,    P9_DOTL_CLOEXEC },
+               { O_SYNC,       P9_DOTL_SYNC},
+       };
+       for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
+               if (flags & dotl_oflag_map[i].open_flag)
+                       rflags |= dotl_oflag_map[i].dotl_flag;
+       }
+       return rflags;
+}
+
+/**
+ * v9fs_open_to_dotl_flags- convert Linux specific open flags to
+ * plan 9 open flag.
+ * @flags: flags to convert
+ */
+int v9fs_open_to_dotl_flags(int flags)
+{
+       int rflags = 0;
+
+       /*
+        * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
+        * and P9_DOTL_NOACCESS
+        */
+       rflags |= flags & O_ACCMODE;
+       rflags |= v9fs_mapped_dotl_flags(flags);
+
+       return rflags;
+}
+
 /**
  * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.
  * @dir: directory inode that is being created
@@ -258,7 +311,8 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
                           "Failed to get acl values in creat %d\n", err);
                goto error;
        }
-       err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid);
+       err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
+                                   mode, gid, &qid);
        if (err < 0) {
                P9_DPRINTK(P9_DEBUG_VFS,
                                "p9_client_open_dotl failed in creat %d\n",
@@ -281,10 +335,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
                P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
                goto error;
        }
-       d_instantiate(dentry, inode);
        err = v9fs_fid_add(dentry, fid);
        if (err < 0)
                goto error;
+       d_instantiate(dentry, inode);
 
        /* Now set the ACL based on the default value */
        v9fs_set_create_acl(dentry, &dacl, &pacl);
@@ -403,10 +457,10 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
                                err);
                        goto error;
                }
-               d_instantiate(dentry, inode);
                err = v9fs_fid_add(dentry, fid);
                if (err < 0)
                        goto error;
+               d_instantiate(dentry, inode);
                fid = NULL;
        } else {
                /*
@@ -414,7 +468,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
                 * inode with stat. We need to get an inode
                 * so that we can set the acl with dentry
                 */
-               inode = v9fs_get_inode(dir->i_sb, mode);
+               inode = v9fs_get_inode(dir->i_sb, mode, 0);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        goto error;
@@ -540,6 +594,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
 void
 v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
 {
+       mode_t mode;
        struct v9fs_inode *v9inode = V9FS_I(inode);
 
        if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
@@ -552,11 +607,10 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
                inode->i_uid = stat->st_uid;
                inode->i_gid = stat->st_gid;
                inode->i_nlink = stat->st_nlink;
-               inode->i_mode = stat->st_mode;
-               inode->i_rdev = new_decode_dev(stat->st_rdev);
 
-               if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode)))
-                       init_special_inode(inode, inode->i_mode, inode->i_rdev);
+               mode = stat->st_mode & S_IALLUGO;
+               mode |= inode->i_mode & ~S_IALLUGO;
+               inode->i_mode = mode;
 
                i_size_write(inode, stat->st_size);
                inode->i_blocks = stat->st_blocks;
@@ -657,14 +711,14 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
                                        err);
                        goto error;
                }
-               d_instantiate(dentry, inode);
                err = v9fs_fid_add(dentry, fid);
                if (err < 0)
                        goto error;
+               d_instantiate(dentry, inode);
                fid = NULL;
        } else {
                /* Not in cached mode. No need to populate inode with stat */
-               inode = v9fs_get_inode(dir->i_sb, S_IFLNK);
+               inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        goto error;
@@ -810,17 +864,17 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
                                err);
                        goto error;
                }
-               d_instantiate(dentry, inode);
                err = v9fs_fid_add(dentry, fid);
                if (err < 0)
                        goto error;
+               d_instantiate(dentry, inode);
                fid = NULL;
        } else {
                /*
                 * Not in cached mode. No need to populate inode with stat.
                 * socket syscall returns a fd, so we need instantiate
                 */
-               inode = v9fs_get_inode(dir->i_sb, mode);
+               inode = v9fs_get_inode(dir->i_sb, mode, rdev);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        goto error;
@@ -886,6 +940,11 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
        st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
        if (IS_ERR(st))
                return PTR_ERR(st);
+       /*
+        * Don't update inode if the file type is different
+        */
+       if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
+               goto out;
 
        spin_lock(&inode->i_lock);
        /*
@@ -897,6 +956,7 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
        if (v9ses->cache)
                inode->i_size = i_size;
        spin_unlock(&inode->i_lock);
+out:
        kfree(st);
        return 0;
 }
index feef6cd..c70251d 100644 (file)
@@ -149,7 +149,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
        else
                sb->s_d_op = &v9fs_dentry_operations;
 
-       inode = v9fs_get_inode(sb, S_IFDIR | mode);
+       inode = v9fs_get_inode(sb, S_IFDIR | mode, 0);
        if (IS_ERR(inode)) {
                retval = PTR_ERR(inode);
                goto release_sb;
index 54b8c28..720d885 100644 (file)
@@ -474,17 +474,22 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
                befs_data_stream *data = &befs_ino->i_data.ds;
                befs_off_t len = data->size;
 
-               befs_debug(sb, "Follow long symlink");
-
-               link = kmalloc(len, GFP_NOFS);
-               if (!link) {
-                       link = ERR_PTR(-ENOMEM);
-               } else if (befs_read_lsymlink(sb, data, link, len) != len) {
-                       kfree(link);
-                       befs_error(sb, "Failed to read entire long symlink");
+               if (len == 0) {
+                       befs_error(sb, "Long symlink with illegal length");
                        link = ERR_PTR(-EIO);
                } else {
-                       link[len - 1] = '\0';
+                       befs_debug(sb, "Follow long symlink");
+
+                       link = kmalloc(len, GFP_NOFS);
+                       if (!link) {
+                               link = ERR_PTR(-ENOMEM);
+                       } else if (befs_read_lsymlink(sb, data, link, len) != len) {
+                               kfree(link);
+                               befs_error(sb, "Failed to read entire long symlink");
+                               link = ERR_PTR(-EIO);
+                       } else {
+                               link[len - 1] = '\0';
+                       }
                }
        } else {
                link = befs_ino->i_data.symlink;
index ff77262..95f786e 100644 (file)
@@ -1429,6 +1429,11 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
                WARN_ON_ONCE(bdev->bd_holders);
                sync_blockdev(bdev);
                kill_bdev(bdev);
+               /* ->release can cause the old bdi to disappear,
+                * so must switch it out first
+                */
+               bdev_inode_switch_bdi(bdev->bd_inode,
+                                       &default_backing_dev_info);
        }
        if (bdev->bd_contains == bdev) {
                if (disk->fops->release)
@@ -1442,8 +1447,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
                disk_put_part(bdev->bd_part);
                bdev->bd_part = NULL;
                bdev->bd_disk = NULL;
-               bdev_inode_switch_bdi(bdev->bd_inode,
-                                       &default_backing_dev_info);
                if (bdev != bdev->bd_contains)
                        victim = bdev->bd_contains;
                bdev->bd_contains = NULL;
index 502b9e9..d9f99a1 100644 (file)
@@ -176,7 +176,11 @@ static inline u64 btrfs_ino(struct inode *inode)
 {
        u64 ino = BTRFS_I(inode)->location.objectid;
 
-       if (ino <= BTRFS_FIRST_FREE_OBJECTID)
+       /*
+        * !ino: btree_inode
+        * type == BTRFS_ROOT_ITEM_KEY: subvol dir
+        */
+       if (!ino || BTRFS_I(inode)->location.type == BTRFS_ROOT_ITEM_KEY)
                ino = inode->i_ino;
        return ino;
 }
index 0469263..03912c5 100644 (file)
@@ -1415,17 +1415,15 @@ void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val);
 #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits)            \
 static inline u##bits btrfs_##name(struct extent_buffer *eb)           \
 {                                                                      \
-       type *p = kmap_atomic(eb->first_page, KM_USER0);                \
+       type *p = page_address(eb->first_page);                         \
        u##bits res = le##bits##_to_cpu(p->member);                     \
-       kunmap_atomic(p, KM_USER0);                                     \
        return res;                                                     \
 }                                                                      \
 static inline void btrfs_set_##name(struct extent_buffer *eb,          \
                                    u##bits val)                        \
 {                                                                      \
-       type *p = kmap_atomic(eb->first_page, KM_USER0);                \
+       type *p = page_address(eb->first_page);                         \
        p->member = cpu_to_le##bits(val);                               \
-       kunmap_atomic(p, KM_USER0);                                     \
 }
 
 #define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits)             \
@@ -2367,8 +2365,8 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
 int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
-int btrfs_drop_snapshot(struct btrfs_root *root,
-                       struct btrfs_block_rsv *block_rsv, int update_ref);
+void btrfs_drop_snapshot(struct btrfs_root *root,
+                        struct btrfs_block_rsv *block_rsv, int update_ref);
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct extent_buffer *node,
index 66bac22..f5be06a 100644 (file)
@@ -1782,6 +1782,9 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
 
 
                for (i = 0; i < multi->num_stripes; i++, stripe++) {
+                       if (!stripe->dev->can_discard)
+                               continue;
+
                        ret = btrfs_issue_discard(stripe->dev->bdev,
                                                  stripe->physical,
                                                  stripe->length);
@@ -1789,11 +1792,16 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
                                discarded_bytes += stripe->length;
                        else if (ret != -EOPNOTSUPP)
                                break;
+
+                       /*
+                        * Just in case we get back EOPNOTSUPP for some reason,
+                        * just ignore the return value so we don't screw up
+                        * people calling discard_extent.
+                        */
+                       ret = 0;
                }
                kfree(multi);
        }
-       if (discarded_bytes && ret == -EOPNOTSUPP)
-               ret = 0;
 
        if (actual_bytes)
                *actual_bytes = discarded_bytes;
@@ -6269,8 +6277,8 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
  * also make sure backrefs for the shared block and all lower level
  * blocks are properly updated.
  */
-int btrfs_drop_snapshot(struct btrfs_root *root,
-                       struct btrfs_block_rsv *block_rsv, int update_ref)
+void btrfs_drop_snapshot(struct btrfs_root *root,
+                        struct btrfs_block_rsv *block_rsv, int update_ref)
 {
        struct btrfs_path *path;
        struct btrfs_trans_handle *trans;
@@ -6283,13 +6291,16 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        int level;
 
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        wc = kzalloc(sizeof(*wc), GFP_NOFS);
        if (!wc) {
                btrfs_free_path(path);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto out;
        }
 
        trans = btrfs_start_transaction(tree_root, 0);
@@ -6318,7 +6329,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                path->lowest_level = 0;
                if (ret < 0) {
                        err = ret;
-                       goto out;
+                       goto out_free;
                }
                WARN_ON(ret > 0);
 
@@ -6425,11 +6436,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                free_extent_buffer(root->commit_root);
                kfree(root);
        }
-out:
+out_free:
        btrfs_end_transaction_throttle(trans, tree_root);
        kfree(wc);
        btrfs_free_path(path);
-       return err;
+out:
+       if (err)
+               btrfs_std_error(root->fs_info, err);
+       return;
 }
 
 /*
@@ -6720,6 +6734,10 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
        struct btrfs_space_info *space_info;
        struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
        struct btrfs_device *device;
+       u64 min_free;
+       u64 dev_min = 1;
+       u64 dev_nr = 0;
+       int index;
        int full = 0;
        int ret = 0;
 
@@ -6729,8 +6747,10 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
        if (!block_group)
                return -1;
 
+       min_free = btrfs_block_group_used(&block_group->item);
+
        /* no bytes used, we're good */
-       if (!btrfs_block_group_used(&block_group->item))
+       if (!min_free)
                goto out;
 
        space_info = block_group->space_info;
@@ -6746,10 +6766,9 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
         * all of the extents from this block group.  If we can, we're good
         */
        if ((space_info->total_bytes != block_group->key.offset) &&
-          (space_info->bytes_used + space_info->bytes_reserved +
-           space_info->bytes_pinned + space_info->bytes_readonly +
-           btrfs_block_group_used(&block_group->item) <
-           space_info->total_bytes)) {
+           (space_info->bytes_used + space_info->bytes_reserved +
+            space_info->bytes_pinned + space_info->bytes_readonly +
+            min_free < space_info->total_bytes)) {
                spin_unlock(&space_info->lock);
                goto out;
        }
@@ -6766,9 +6785,31 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
        if (full)
                goto out;
 
+       /*
+        * index:
+        *      0: raid10
+        *      1: raid1
+        *      2: dup
+        *      3: raid0
+        *      4: single
+        */
+       index = get_block_group_index(block_group);
+       if (index == 0) {
+               dev_min = 4;
+               /* Divide by 2 */
+               min_free >>= 1;
+       } else if (index == 1) {
+               dev_min = 2;
+       } else if (index == 2) {
+               /* Multiply by 2 */
+               min_free <<= 1;
+       } else if (index == 3) {
+               dev_min = fs_devices->rw_devices;
+               do_div(min_free, dev_min);
+       }
+
        mutex_lock(&root->fs_info->chunk_mutex);
        list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
-               u64 min_free = btrfs_block_group_used(&block_group->item);
                u64 dev_offset;
 
                /*
@@ -6779,7 +6820,11 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
                        ret = find_free_dev_extent(NULL, device, min_free,
                                                   &dev_offset, NULL);
                        if (!ret)
+                               dev_nr++;
+
+                       if (dev_nr >= dev_min)
                                break;
+
                        ret = -1;
                }
        }
index b910694..a1cb782 100644 (file)
@@ -183,8 +183,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
         * read from the commit root and sidestep a nasty deadlock
         * between reading the free space cache and updating the csum tree.
         */
-       if (btrfs_is_free_space_inode(root, inode))
+       if (btrfs_is_free_space_inode(root, inode)) {
                path->search_commit_root = 1;
+               path->skip_locking = 1;
+       }
 
        disk_bytenr = (u64)bio->bi_sector << 9;
        if (dio)
index 658d669..3c3abff 100644 (file)
@@ -150,6 +150,8 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
        spin_lock(&root->fs_info->defrag_inodes_lock);
        if (!BTRFS_I(inode)->in_defrag)
                __btrfs_add_inode_defrag(inode, defrag);
+       else
+               kfree(defrag);
        spin_unlock(&root->fs_info->defrag_inodes_lock);
        return 0;
 }
@@ -1073,12 +1075,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
        start_pos = pos & ~((u64)root->sectorsize - 1);
        last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT;
 
-       if (start_pos > inode->i_size) {
-               err = btrfs_cont_expand(inode, i_size_read(inode), start_pos);
-               if (err)
-                       return err;
-       }
-
 again:
        for (i = 0; i < num_pages; i++) {
                pages[i] = find_or_create_page(inode->i_mapping, index + i,
@@ -1336,6 +1332,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
        struct inode *inode = fdentry(file)->d_inode;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        loff_t *ppos = &iocb->ki_pos;
+       u64 start_pos;
        ssize_t num_written = 0;
        ssize_t err = 0;
        size_t count, ocount;
@@ -1384,6 +1381,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
        file_update_time(file);
        BTRFS_I(inode)->sequence++;
 
+       start_pos = round_down(pos, root->sectorsize);
+       if (start_pos > i_size_read(inode)) {
+               err = btrfs_cont_expand(inode, i_size_read(inode), start_pos);
+               if (err) {
+                       mutex_unlock(&inode->i_mutex);
+                       goto out;
+               }
+       }
+
        if (unlikely(file->f_flags & O_DIRECT)) {
                num_written = __btrfs_direct_write(iocb, iov, nr_segs,
                                                   pos, ppos, count, ocount);
@@ -1638,11 +1644,15 @@ static long btrfs_fallocate(struct file *file, int mode,
 
        cur_offset = alloc_start;
        while (1) {
+               u64 actual_end;
+
                em = btrfs_get_extent(inode, NULL, 0, cur_offset,
                                      alloc_end - cur_offset, 0);
                BUG_ON(IS_ERR_OR_NULL(em));
                last_byte = min(extent_map_end(em), alloc_end);
+               actual_end = min_t(u64, extent_map_end(em), offset + len);
                last_byte = (last_byte + mask) & ~mask;
+
                if (em->block_start == EXTENT_MAP_HOLE ||
                    (cur_offset >= inode->i_size &&
                     !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
@@ -1655,6 +1665,16 @@ static long btrfs_fallocate(struct file *file, int mode,
                                free_extent_map(em);
                                break;
                        }
+               } else if (actual_end > inode->i_size &&
+                          !(mode & FALLOC_FL_KEEP_SIZE)) {
+                       /*
+                        * We didn't need to allocate any more space, but we
+                        * still extended the size of the file so we need to
+                        * update i_size.
+                        */
+                       inode->i_ctime = CURRENT_TIME;
+                       i_size_write(inode, actual_end);
+                       btrfs_ordered_update_i_size(inode, actual_end, NULL);
                }
                free_extent_map(em);
 
@@ -1804,10 +1824,14 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
                }
        }
 
-       if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
-               return -EINVAL;
-       if (offset > inode->i_sb->s_maxbytes)
-               return -EINVAL;
+       if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) {
+               ret = -EINVAL;
+               goto out;
+       }
+       if (offset > inode->i_sb->s_maxbytes) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        /* Special lock needed here? */
        if (offset != file->f_pos) {
index 6377713..41ac927 100644 (file)
@@ -190,9 +190,11 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
                                    struct btrfs_path *path,
                                    struct inode *inode)
 {
+       struct btrfs_block_rsv *rsv;
        loff_t oldsize;
        int ret = 0;
 
+       rsv = trans->block_rsv;
        trans->block_rsv = root->orphan_block_rsv;
        ret = btrfs_block_rsv_check(trans, root,
                                    root->orphan_block_rsv,
@@ -210,6 +212,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
         */
        ret = btrfs_truncate_inode_items(trans, root, inode,
                                         0, BTRFS_EXTENT_DATA_KEY);
+
+       trans->block_rsv = rsv;
        if (ret) {
                WARN_ON(1);
                return ret;
@@ -1168,9 +1172,9 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl)
                div64_u64(extent_bytes, (sizeof(struct btrfs_free_space)));
 }
 
-static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
-                             struct btrfs_free_space *info, u64 offset,
-                             u64 bytes)
+static inline void __bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
+                                      struct btrfs_free_space *info,
+                                      u64 offset, u64 bytes)
 {
        unsigned long start, count;
 
@@ -1181,6 +1185,13 @@ static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
        bitmap_clear(info->bitmap, start, count);
 
        info->bytes -= bytes;
+}
+
+static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
+                             struct btrfs_free_space *info, u64 offset,
+                             u64 bytes)
+{
+       __bitmap_clear_bits(ctl, info, offset, bytes);
        ctl->free_space -= bytes;
 }
 
@@ -1984,7 +1995,7 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
                return 0;
 
        ret = search_start;
-       bitmap_clear_bits(ctl, entry, ret, bytes);
+       __bitmap_clear_bits(ctl, entry, ret, bytes);
 
        return ret;
 }
@@ -2039,7 +2050,6 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
                                continue;
                        }
                } else {
-
                        ret = entry->offset;
 
                        entry->offset += bytes;
index 15fceef..4d14de6 100644 (file)
@@ -1786,7 +1786,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
                          &ordered_extent->list);
 
        ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
-       if (!ret) {
+       if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
                ret = btrfs_update_inode(trans, root, inode);
                BUG_ON(ret);
        }
@@ -3510,15 +3510,19 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
                        err = btrfs_drop_extents(trans, inode, cur_offset,
                                                 cur_offset + hole_size,
                                                 &hint_byte, 1);
-                       if (err)
+                       if (err) {
+                               btrfs_end_transaction(trans, root);
                                break;
+                       }
 
                        err = btrfs_insert_file_extent(trans, root,
                                        btrfs_ino(inode), cur_offset, 0,
                                        0, hole_size, 0, hole_size,
                                        0, 0, 0);
-                       if (err)
+                       if (err) {
+                               btrfs_end_transaction(trans, root);
                                break;
+                       }
 
                        btrfs_drop_extent_cache(inode, hole_start,
                                        last_byte - 1, 0);
@@ -3952,7 +3956,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
                         struct btrfs_root *root, int *new)
 {
        struct inode *inode;
-       int bad_inode = 0;
 
        inode = btrfs_iget_locked(s, location->objectid, root);
        if (!inode)
@@ -3968,15 +3971,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
                        if (new)
                                *new = 1;
                } else {
-                       bad_inode = 1;
+                       unlock_new_inode(inode);
+                       iput(inode);
+                       inode = ERR_PTR(-ESTALE);
                }
        }
 
-       if (bad_inode) {
-               iput(inode);
-               inode = ERR_PTR(-ESTALE);
-       }
-
        return inode;
 }
 
@@ -5823,7 +5823,7 @@ again:
 
        add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
        ret = btrfs_ordered_update_i_size(inode, 0, ordered);
-       if (!ret)
+       if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags))
                btrfs_update_inode(trans, root, inode);
        ret = 0;
 out_unlock:
@@ -7354,11 +7354,15 @@ static int btrfs_set_page_dirty(struct page *page)
 static int btrfs_permission(struct inode *inode, int mask)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
+       umode_t mode = inode->i_mode;
 
-       if (btrfs_root_readonly(root) && (mask & MAY_WRITE))
-               return -EROFS;
-       if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE))
-               return -EACCES;
+       if (mask & MAY_WRITE &&
+           (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) {
+               if (btrfs_root_readonly(root))
+                       return -EROFS;
+               if (BTRFS_I(inode)->flags & BTRFS_INODE_READONLY)
+                       return -EACCES;
+       }
        return generic_permission(inode, mask);
 }
 
index 7cf0133..3351b1b 100644 (file)
@@ -2220,6 +2220,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
            !IS_ALIGNED(destoff, bs))
                goto out_unlock;
 
+       if (destoff > inode->i_size) {
+               ret = btrfs_cont_expand(inode, inode->i_size, destoff);
+               if (ret)
+                       goto out_unlock;
+       }
+
        /* do any pending delalloc/csum calc on src, one way or
           another, and lock file content */
        while (1) {
@@ -2236,6 +2242,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                btrfs_wait_ordered_range(src, off, len);
        }
 
+       /* truncate page cache pages from target inode range */
+       truncate_inode_pages_range(&inode->i_data, off,
+                                  ALIGN(off + len, PAGE_CACHE_SIZE) - 1);
+
        /* clone data */
        key.objectid = btrfs_ino(src);
        key.type = BTRFS_EXTENT_DATA_KEY;
@@ -2321,14 +2331,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
 
                        if (type == BTRFS_FILE_EXTENT_REG ||
                            type == BTRFS_FILE_EXTENT_PREALLOC) {
+                               /*
+                                *    a  | --- range to clone ---|  b
+                                * | ------------- extent ------------- |
+                                */
+
+                               /* substract range b */
+                               if (key.offset + datal > off + len)
+                                       datal = off + len - key.offset;
+
+                               /* substract range a */
                                if (off > key.offset) {
                                        datao += off - key.offset;
                                        datal -= off - key.offset;
                                }
 
-                               if (key.offset + datal > off + len)
-                                       datal = off + len - key.offset;
-
                                ret = btrfs_drop_extents(trans, inode,
                                                         new_key.offset,
                                                         new_key.offset + datal,
index 7dc36fa..e24b796 100644 (file)
@@ -884,6 +884,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        struct btrfs_root *tree_root = fs_info->tree_root;
        struct btrfs_root *root = pending->root;
        struct btrfs_root *parent_root;
+       struct btrfs_block_rsv *rsv;
        struct inode *parent_inode;
        struct dentry *parent;
        struct dentry *dentry;
@@ -895,6 +896,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        u64 objectid;
        u64 root_flags;
 
+       rsv = trans->block_rsv;
+
        new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
        if (!new_root_item) {
                pending->error = -ENOMEM;
@@ -1002,6 +1005,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_orphan_post_snapshot(trans, pending);
 fail:
        kfree(new_root_item);
+       trans->block_rsv = rsv;
        btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);
        return 0;
 }
index babee65..786639f 100644 (file)
@@ -799,14 +799,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
                                  struct extent_buffer *eb, int slot,
                                  struct btrfs_key *key)
 {
-       struct inode *dir;
-       int ret;
        struct btrfs_inode_ref *ref;
+       struct btrfs_dir_item *di;
+       struct inode *dir;
        struct inode *inode;
-       char *name;
-       int namelen;
        unsigned long ref_ptr;
        unsigned long ref_end;
+       char *name;
+       int namelen;
+       int ret;
        int search_done = 0;
 
        /*
@@ -909,6 +910,25 @@ again:
        }
        btrfs_release_path(path);
 
+       /* look for a conflicting sequence number */
+       di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir),
+                                        btrfs_inode_ref_index(eb, ref),
+                                        name, namelen, 0);
+       if (di && !IS_ERR(di)) {
+               ret = drop_one_dir_item(trans, root, path, dir, di);
+               BUG_ON(ret);
+       }
+       btrfs_release_path(path);
+
+       /* look for a conflicing name */
+       di = btrfs_lookup_dir_item(trans, root, path, btrfs_ino(dir),
+                                  name, namelen, 0);
+       if (di && !IS_ERR(di)) {
+               ret = drop_one_dir_item(trans, root, path, dir, di);
+               BUG_ON(ret);
+       }
+       btrfs_release_path(path);
+
 insert:
        /* insert our name */
        ret = btrfs_add_link(trans, dir, inode, name, namelen, 0,
index 53875ae..f2a4cc7 100644 (file)
@@ -142,6 +142,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
        unsigned long limit;
        unsigned long last_waited = 0;
        int force_reg = 0;
+       int sync_pending = 0;
        struct blk_plug plug;
 
        /*
@@ -229,6 +230,22 @@ loop_lock:
 
                BUG_ON(atomic_read(&cur->bi_cnt) == 0);
 
+               /*
+                * if we're doing the sync list, record that our
+                * plug has some sync requests on it
+                *
+                * If we're doing the regular list and there are
+                * sync requests sitting around, unplug before
+                * we add more
+                */
+               if (pending_bios == &device->pending_sync_bios) {
+                       sync_pending = 1;
+               } else if (sync_pending) {
+                       blk_finish_plug(&plug);
+                       blk_start_plug(&plug);
+                       sync_pending = 0;
+               }
+
                submit_bio(cur->bi_rw, cur);
                num_run++;
                batch_run++;
@@ -500,6 +517,9 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
                        fs_devices->rw_devices--;
                }
 
+               if (device->can_discard)
+                       fs_devices->num_can_discard--;
+
                new_device = kmalloc(sizeof(*new_device), GFP_NOFS);
                BUG_ON(!new_device);
                memcpy(new_device, device, sizeof(*new_device));
@@ -508,6 +528,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
                new_device->bdev = NULL;
                new_device->writeable = 0;
                new_device->in_fs_metadata = 0;
+               new_device->can_discard = 0;
                list_replace_rcu(&device->dev_list, &new_device->dev_list);
 
                call_rcu(&device->rcu, free_device);
@@ -547,6 +568,7 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
 static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
                                fmode_t flags, void *holder)
 {
+       struct request_queue *q;
        struct block_device *bdev;
        struct list_head *head = &fs_devices->devices;
        struct btrfs_device *device;
@@ -603,6 +625,12 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
                        seeding = 0;
                }
 
+               q = bdev_get_queue(bdev);
+               if (blk_queue_discard(q)) {
+                       device->can_discard = 1;
+                       fs_devices->num_can_discard++;
+               }
+
                device->bdev = bdev;
                device->in_fs_metadata = 0;
                device->mode = flags;
@@ -835,6 +863,7 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans,
 
        max_hole_start = search_start;
        max_hole_size = 0;
+       hole_size = 0;
 
        if (search_start >= search_end) {
                ret = -ENOSPC;
@@ -917,7 +946,14 @@ next:
                cond_resched();
        }
 
-       hole_size = search_end- search_start;
+       /*
+        * At this point, search_start should be the end of
+        * allocated dev extents, and when shrinking the device,
+        * search_end may be smaller than search_start.
+        */
+       if (search_end > search_start)
+               hole_size = search_end - search_start;
+
        if (hole_size > max_hole_size) {
                max_hole_start = search_start;
                max_hole_size = hole_size;
@@ -1543,6 +1579,7 @@ error:
 
 int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 {
+       struct request_queue *q;
        struct btrfs_trans_handle *trans;
        struct btrfs_device *device;
        struct block_device *bdev;
@@ -1612,6 +1649,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 
        lock_chunks(root);
 
+       q = bdev_get_queue(bdev);
+       if (blk_queue_discard(q))
+               device->can_discard = 1;
        device->writeable = 1;
        device->work.func = pending_bios_fn;
        generate_random_uuid(device->uuid);
@@ -1647,6 +1687,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
        root->fs_info->fs_devices->num_devices++;
        root->fs_info->fs_devices->open_devices++;
        root->fs_info->fs_devices->rw_devices++;
+       if (device->can_discard)
+               root->fs_info->fs_devices->num_can_discard++;
        root->fs_info->fs_devices->total_rw_bytes += device->total_bytes;
 
        if (!blk_queue_nonrot(bdev_get_queue(bdev)))
@@ -2413,9 +2455,10 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                        total_avail = device->total_bytes - device->bytes_used;
                else
                        total_avail = 0;
-               /* avail is off by max(alloc_start, 1MB), but that is the same
-                * for all devices, so it doesn't hurt the sorting later on
-                */
+
+               /* If there is no space on this device, skip it. */
+               if (total_avail == 0)
+                       continue;
 
                ret = find_free_dev_extent(trans, device,
                                           max_stripe_size * dev_stripes,
index 7c12d61..6d866db 100644 (file)
@@ -48,6 +48,7 @@ struct btrfs_device {
        int writeable;
        int in_fs_metadata;
        int missing;
+       int can_discard;
 
        spinlock_t io_lock;
 
@@ -104,6 +105,7 @@ struct btrfs_fs_devices {
        u64 rw_devices;
        u64 missing_devices;
        u64 total_rw_bytes;
+       u64 num_can_discard;
        struct block_device *latest_bdev;
 
        /* all of the devices in the FS, protected by a mutex
index d733b9c..69565e5 100644 (file)
@@ -116,6 +116,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
                if (ret)
                        goto out;
                btrfs_release_path(path);
+
+               /*
+                * remove the attribute
+                */
+               if (!value)
+                       goto out;
        }
 
 again:
@@ -158,6 +164,9 @@ out:
        return ret;
 }
 
+/*
+ * @value: "" makes the attribute to empty, NULL removes it
+ */
 int __btrfs_setxattr(struct btrfs_trans_handle *trans,
                     struct inode *inode, const char *name,
                     const void *value, size_t size, int flags)
index fee028b..86c59e1 100644 (file)
@@ -1595,7 +1595,7 @@ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry,
                r = build_dentry_path(rdentry, ppath, pathlen, ino, freepath);
                dout(" dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen,
                     *ppath);
-       } else if (rpath) {
+       } else if (rpath || rino) {
                *ino = rino;
                *ppath = rpath;
                *pathlen = strlen(rpath);
index d47c5ec..88bacaf 100644 (file)
@@ -813,8 +813,8 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
        fsc = create_fs_client(fsopt, opt);
        if (IS_ERR(fsc)) {
                res = ERR_CAST(fsc);
-               kfree(fsopt);
-               kfree(opt);
+               destroy_mount_options(fsopt);
+               ceph_destroy_options(opt);
                goto out_final;
        }
 
index 2fe3cf1..6d40656 100644 (file)
@@ -176,7 +176,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
 
 #ifdef CONFIG_CIFS_STATS2
                        seq_printf(m, " In Send: %d In MaxReq Wait: %d",
-                               atomic_read(&server->inSend),
+                               atomic_read(&server->in_send),
                                atomic_read(&server->num_waiters));
 #endif
 
index 21de1d6..d0f59fa 100644 (file)
@@ -991,24 +991,6 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
        return pntsd;
 }
 
-static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
-               struct cifs_ntsd *pnntsd, u32 acllen)
-{
-       int xid, rc;
-       struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-
-       if (IS_ERR(tlink))
-               return PTR_ERR(tlink);
-
-       xid = GetXid();
-       rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
-       FreeXid(xid);
-       cifs_put_tlink(tlink);
-
-       cFYI(DBG2, "SetCIFSACL rc = %d", rc);
-       return rc;
-}
-
 static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
                struct cifs_ntsd *pnntsd, u32 acllen)
 {
@@ -1047,18 +1029,10 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
                                struct inode *inode, const char *path)
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-       struct cifsFileInfo *open_file;
-       int rc;
 
        cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
 
-       open_file = find_readable_file(CIFS_I(inode), true);
-       if (!open_file)
-               return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
-
-       rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
-       cifsFileInfo_put(open_file);
-       return rc;
+       return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
 }
 
 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
index cb71dc1..95da802 100644 (file)
@@ -125,5 +125,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "1.74"
+#define CIFS_VERSION   "1.75"
 #endif                         /* _CIFSFS_H */
index 38ce6d4..95dad9d 100644 (file)
@@ -291,7 +291,7 @@ struct TCP_Server_Info {
        struct fscache_cookie   *fscache; /* client index cache cookie */
 #endif
 #ifdef CONFIG_CIFS_STATS2
-       atomic_t inSend; /* requests trying to send */
+       atomic_t in_send; /* requests trying to send */
        atomic_t num_waiters;   /* blocked waiting to get in sendrecv */
 #endif
 };
@@ -672,12 +672,54 @@ struct mid_q_entry {
        bool multiEnd:1;        /* both received */
 };
 
-struct oplock_q_entry {
-       struct list_head qhead;
-       struct inode *pinode;
-       struct cifs_tcon *tcon;
-       __u16 netfid;
-};
+/*     Make code in transport.c a little cleaner by moving
+       update of optional stats into function below */
+#ifdef CONFIG_CIFS_STATS2
+
+static inline void cifs_in_send_inc(struct TCP_Server_Info *server)
+{
+       atomic_inc(&server->in_send);
+}
+
+static inline void cifs_in_send_dec(struct TCP_Server_Info *server)
+{
+       atomic_dec(&server->in_send);
+}
+
+static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server)
+{
+       atomic_inc(&server->num_waiters);
+}
+
+static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server)
+{
+       atomic_dec(&server->num_waiters);
+}
+
+static inline void cifs_save_when_sent(struct mid_q_entry *mid)
+{
+       mid->when_sent = jiffies;
+}
+#else
+static inline void cifs_in_send_inc(struct TCP_Server_Info *server)
+{
+}
+static inline void cifs_in_send_dec(struct TCP_Server_Info *server)
+{
+}
+
+static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server)
+{
+}
+
+static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server)
+{
+}
+
+static inline void cifs_save_when_sent(struct mid_q_entry *mid)
+{
+}
+#endif
 
 /* for pending dnotify requests */
 struct dir_notify_req {
index 80c2e3a..633c246 100644 (file)
@@ -2878,7 +2878,8 @@ cleanup_volume_info_contents(struct smb_vol *volume_info)
        kfree(volume_info->username);
        kzfree(volume_info->password);
        kfree(volume_info->UNC);
-       kfree(volume_info->UNCip);
+       if (volume_info->UNCip != volume_info->UNC + 2)
+               kfree(volume_info->UNCip);
        kfree(volume_info->domainname);
        kfree(volume_info->iocharset);
        kfree(volume_info->prepath);
index ae576fb..72d448b 100644 (file)
@@ -105,8 +105,8 @@ cifs_bp_rename_retry:
        }
        rcu_read_unlock();
        if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
-               cERROR(1, "did not end path lookup where expected namelen is %d",
-                       namelen);
+               cFYI(1, "did not end path lookup where expected. namelen=%d "
+                       "dfsplen=%d", namelen, dfsplen);
                /* presumably this is only possible if racing with a rename
                of one of the parent directories  (we can not lock the dentries
                above us to prevent this, but retrying should be harmless) */
index c1b9c4b..10ca6b2 100644 (file)
@@ -266,15 +266,11 @@ static int wait_for_free_request(struct TCP_Server_Info *server,
        while (1) {
                if (atomic_read(&server->inFlight) >= cifs_max_pending) {
                        spin_unlock(&GlobalMid_Lock);
-#ifdef CONFIG_CIFS_STATS2
-                       atomic_inc(&server->num_waiters);
-#endif
+                       cifs_num_waiters_inc(server);
                        wait_event(server->request_q,
                                   atomic_read(&server->inFlight)
                                     < cifs_max_pending);
-#ifdef CONFIG_CIFS_STATS2
-                       atomic_dec(&server->num_waiters);
-#endif
+                       cifs_num_waiters_dec(server);
                        spin_lock(&GlobalMid_Lock);
                } else {
                        if (server->tcpStatus == CifsExiting) {
@@ -381,15 +377,13 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
        mid->callback = callback;
        mid->callback_data = cbdata;
        mid->midState = MID_REQUEST_SUBMITTED;
-#ifdef CONFIG_CIFS_STATS2
-       atomic_inc(&server->inSend);
-#endif
+
+       cifs_in_send_inc(server);
        rc = smb_sendv(server, iov, nvec);
-#ifdef CONFIG_CIFS_STATS2
-       atomic_dec(&server->inSend);
-       mid->when_sent = jiffies;
-#endif
+       cifs_in_send_dec(server);
+       cifs_save_when_sent(mid);
        mutex_unlock(&server->srv_mutex);
+
        if (rc)
                goto out_err;
 
@@ -575,14 +569,10 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
        }
 
        midQ->midState = MID_REQUEST_SUBMITTED;
-#ifdef CONFIG_CIFS_STATS2
-       atomic_inc(&ses->server->inSend);
-#endif
+       cifs_in_send_inc(ses->server);
        rc = smb_sendv(ses->server, iov, n_vec);
-#ifdef CONFIG_CIFS_STATS2
-       atomic_dec(&ses->server->inSend);
-       midQ->when_sent = jiffies;
-#endif
+       cifs_in_send_dec(ses->server);
+       cifs_save_when_sent(midQ);
 
        mutex_unlock(&ses->server->srv_mutex);
 
@@ -703,14 +693,11 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
        }
 
        midQ->midState = MID_REQUEST_SUBMITTED;
-#ifdef CONFIG_CIFS_STATS2
-       atomic_inc(&ses->server->inSend);
-#endif
+
+       cifs_in_send_inc(ses->server);
        rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
-#ifdef CONFIG_CIFS_STATS2
-       atomic_dec(&ses->server->inSend);
-       midQ->when_sent = jiffies;
-#endif
+       cifs_in_send_dec(ses->server);
+       cifs_save_when_sent(midQ);
        mutex_unlock(&ses->server->srv_mutex);
 
        if (rc < 0)
@@ -843,14 +830,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
        }
 
        midQ->midState = MID_REQUEST_SUBMITTED;
-#ifdef CONFIG_CIFS_STATS2
-       atomic_inc(&ses->server->inSend);
-#endif
+       cifs_in_send_inc(ses->server);
        rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
-#ifdef CONFIG_CIFS_STATS2
-       atomic_dec(&ses->server->inSend);
-       midQ->when_sent = jiffies;
-#endif
+       cifs_in_send_dec(ses->server);
+       cifs_save_when_sent(midQ);
        mutex_unlock(&ses->server->srv_mutex);
 
        if (rc < 0) {
index 0b48d01..58b1da4 100644 (file)
@@ -1675,11 +1675,6 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 }
 #endif /* HAVE_SET_RESTORE_SIGMASK */
 
-long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
-{
-       return sys_ni_syscall();
-}
-
 #ifdef CONFIG_EPOLL
 
 #ifdef HAVE_SET_RESTORE_SIGMASK
index e717dfd..b7d7bd0 100644 (file)
@@ -175,6 +175,7 @@ struct mpage_da_data {
  */
 #define        EXT4_IO_END_UNWRITTEN   0x0001
 #define EXT4_IO_END_ERROR      0x0002
+#define EXT4_IO_END_QUEUED     0x0004
 
 struct ext4_io_page {
        struct page     *p_page;
index bb85757..5802fa1 100644 (file)
@@ -289,10 +289,10 @@ static inline int ext4_should_order_data(struct inode *inode)
 
 static inline int ext4_should_writeback_data(struct inode *inode)
 {
-       if (!S_ISREG(inode->i_mode))
-               return 0;
        if (EXT4_JOURNAL(inode) == NULL)
                return 1;
+       if (!S_ISREG(inode->i_mode))
+               return 0;
        if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
                return 0;
        if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
index b8602cd..0962642 100644 (file)
@@ -800,12 +800,17 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
        }
 
 retry:
-       if (rw == READ && ext4_should_dioread_nolock(inode))
+       if (rw == READ && ext4_should_dioread_nolock(inode)) {
+               if (unlikely(!list_empty(&ei->i_completed_io_list))) {
+                       mutex_lock(&inode->i_mutex);
+                       ext4_flush_completed_IO(inode);
+                       mutex_unlock(&inode->i_mutex);
+               }
                ret = __blockdev_direct_IO(rw, iocb, inode,
                                 inode->i_sb->s_bdev, iov,
                                 offset, nr_segs,
                                 ext4_get_block, NULL, NULL, 0);
-       else {
+       else {
                ret = blockdev_direct_IO(rw, iocb, inode, iov,
                                 offset, nr_segs, ext4_get_block);
 
index d47264c..18d2558 100644 (file)
@@ -120,6 +120,9 @@ void ext4_evict_inode(struct inode *inode)
        int err;
 
        trace_ext4_evict_inode(inode);
+
+       ext4_ioend_wait(inode);
+
        if (inode->i_nlink) {
                /*
                 * When journalling data dirty buffers are tracked only in the
@@ -983,6 +986,8 @@ static int ext4_journalled_write_end(struct file *file,
        from = pos & (PAGE_CACHE_SIZE - 1);
        to = from + len;
 
+       BUG_ON(!ext4_handle_valid(handle));
+
        if (copied < len) {
                if (!PageUptodate(page))
                        copied = 0;
@@ -1283,7 +1288,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
                        else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
                                err = ext4_bio_write_page(&io_submit, page,
                                                          len, mpd->wbc);
-                       else
+                       else if (buffer_uninit(page_bufs)) {
+                               ext4_set_bh_endio(page_bufs, inode);
+                               err = block_write_full_page_endio(page,
+                                       noalloc_get_block_write,
+                                       mpd->wbc, ext4_end_io_buffer_write);
+                       } else
                                err = block_write_full_page(page,
                                        noalloc_get_block_write, mpd->wbc);
 
@@ -1699,6 +1709,8 @@ static int __ext4_journalled_writepage(struct page *page,
                goto out;
        }
 
+       BUG_ON(!ext4_handle_valid(handle));
+
        ret = walk_page_buffers(handle, page_bufs, 0, len, NULL,
                                do_journal_get_write_access);
 
@@ -2668,8 +2680,15 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
                goto out;
        }
 
-       io_end->flag = EXT4_IO_END_UNWRITTEN;
+       /*
+        * It may be over-defensive here to check EXT4_IO_END_UNWRITTEN now,
+        * but being more careful is always safe for the future change.
+        */
        inode = io_end->inode;
+       if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
+               io_end->flag |= EXT4_IO_END_UNWRITTEN;
+               atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
+       }
 
        /* Add the io_end to per-inode completed io list*/
        spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
index 430c401..92f38ee 100644 (file)
@@ -142,7 +142,23 @@ static void ext4_end_io_work(struct work_struct *work)
        unsigned long           flags;
        int                     ret;
 
-       mutex_lock(&inode->i_mutex);
+       if (!mutex_trylock(&inode->i_mutex)) {
+               /*
+                * Requeue the work instead of waiting so that the work
+                * items queued after this can be processed.
+                */
+               queue_work(EXT4_SB(inode->i_sb)->dio_unwritten_wq, &io->work);
+               /*
+                * To prevent the ext4-dio-unwritten thread from keeping
+                * requeueing end_io requests and occupying cpu for too long,
+                * yield the cpu if it sees an end_io request that has already
+                * been requeued.
+                */
+               if (io->flag & EXT4_IO_END_QUEUED)
+                       yield();
+               io->flag |= EXT4_IO_END_QUEUED;
+               return;
+       }
        ret = ext4_end_io_nolock(io);
        if (ret < 0) {
                mutex_unlock(&inode->i_mutex);
@@ -334,8 +350,10 @@ submit_and_retry:
        if ((io_end->num_io_pages >= MAX_IO_PAGES) &&
            (io_end->pages[io_end->num_io_pages-1] != io_page))
                goto submit_and_retry;
-       if (buffer_uninit(bh))
-               io->io_end->flag |= EXT4_IO_END_UNWRITTEN;
+       if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
+               io_end->flag |= EXT4_IO_END_UNWRITTEN;
+               atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
+       }
        io->io_end->size += bh->b_size;
        io->io_next_block++;
        ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
index 4687fea..44d0c8d 100644 (file)
@@ -919,7 +919,6 @@ static void ext4_i_callback(struct rcu_head *head)
 
 static void ext4_destroy_inode(struct inode *inode)
 {
-       ext4_ioend_wait(inode);
        if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
                ext4_msg(inode->i_sb, KERN_ERR,
                         "Inode %lu (%p): orphan list check failed!",
index 4ad6473..5efbd5d 100644 (file)
@@ -1231,7 +1231,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
        struct super_block *sb = dir->i_sb;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
        struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */
-       struct msdos_dir_entry *de;
+       struct msdos_dir_entry *uninitialized_var(de);
        int err, free_slots, i, nr_bhs;
        loff_t pos, i_pos;
 
index 5942fec..1726d73 100644 (file)
@@ -1188,9 +1188,9 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
 out:
        /* UTF-8 doesn't provide FAT semantics */
        if (!strcmp(opts->iocharset, "utf8")) {
-               fat_msg(sb, KERN_ERR, "utf8 is not a recommended IO charset"
+               fat_msg(sb, KERN_WARNING, "utf8 is not a recommended IO charset"
                       " for FAT filesystems, filesystem will be "
-                      "case sensitive!\n");
+                      "case sensitive!");
        }
 
        /* If user doesn't specify allow_utime, it's initialized from dmask. */
@@ -1367,6 +1367,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
        sbi->free_clusters = -1;        /* Don't know yet */
        sbi->free_clus_valid = 0;
        sbi->prev_free = FAT_START_ENT;
+       sb->s_maxbytes = 0xffffffff;
 
        if (!sbi->fat_length && b->fat32_length) {
                struct fat_boot_fsinfo *fsinfo;
@@ -1377,8 +1378,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
                sbi->fat_length = le32_to_cpu(b->fat32_length);
                sbi->root_cluster = le32_to_cpu(b->root_cluster);
 
-               sb->s_maxbytes = 0xffffffff;
-
                /* MC - if info_sector is 0, don't multiply by 0 */
                sbi->fsinfo_sector = le16_to_cpu(b->info_sector);
                if (sbi->fsinfo_sector == 0)
index 640fc22..5cb8614 100644 (file)
@@ -258,10 +258,14 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
        forget->forget_one.nlookup = nlookup;
 
        spin_lock(&fc->lock);
-       fc->forget_list_tail->next = forget;
-       fc->forget_list_tail = forget;
-       wake_up(&fc->waitq);
-       kill_fasync(&fc->fasync, SIGIO, POLL_IN);
+       if (fc->connected) {
+               fc->forget_list_tail->next = forget;
+               fc->forget_list_tail = forget;
+               wake_up(&fc->waitq);
+               kill_fasync(&fc->fasync, SIGIO, POLL_IN);
+       } else {
+               kfree(forget);
+       }
        spin_unlock(&fc->lock);
 }
 
@@ -1358,6 +1362,10 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
        if (outarg.namelen > FUSE_NAME_MAX)
                goto err;
 
+       err = -EINVAL;
+       if (size != sizeof(outarg) + outarg.namelen + 1)
+               goto err;
+
        name.name = buf;
        name.len = outarg.namelen;
        err = fuse_copy_one(cs, buf, outarg.namelen + 1);
index d480d9a..594f07a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/compat.h>
+#include <linux/swap.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -245,6 +246,12 @@ void fuse_release_common(struct file *file, int opcode)
        req = ff->reserved_req;
        fuse_prepare_release(ff, file->f_flags, opcode);
 
+       if (ff->flock) {
+               struct fuse_release_in *inarg = &req->misc.release.in;
+               inarg->release_flags |= FUSE_RELEASE_FLOCK_UNLOCK;
+               inarg->lock_owner = fuse_lock_owner_id(ff->fc,
+                                                      (fl_owner_t) file);
+       }
        /* Hold vfsmount and dentry until release is finished */
        path_get(&file->f_path);
        req->misc.release.path = file->f_path;
@@ -755,18 +762,6 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file,
        return req->misc.write.out.size;
 }
 
-static int fuse_write_begin(struct file *file, struct address_space *mapping,
-                       loff_t pos, unsigned len, unsigned flags,
-                       struct page **pagep, void **fsdata)
-{
-       pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-
-       *pagep = grab_cache_page_write_begin(mapping, index, flags);
-       if (!*pagep)
-               return -ENOMEM;
-       return 0;
-}
-
 void fuse_write_update_size(struct inode *inode, loff_t pos)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
@@ -779,62 +774,6 @@ void fuse_write_update_size(struct inode *inode, loff_t pos)
        spin_unlock(&fc->lock);
 }
 
-static int fuse_buffered_write(struct file *file, struct inode *inode,
-                              loff_t pos, unsigned count, struct page *page)
-{
-       int err;
-       size_t nres;
-       struct fuse_conn *fc = get_fuse_conn(inode);
-       unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
-       struct fuse_req *req;
-
-       if (is_bad_inode(inode))
-               return -EIO;
-
-       /*
-        * Make sure writepages on the same page are not mixed up with
-        * plain writes.
-        */
-       fuse_wait_on_page_writeback(inode, page->index);
-
-       req = fuse_get_req(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
-       req->in.argpages = 1;
-       req->num_pages = 1;
-       req->pages[0] = page;
-       req->page_offset = offset;
-       nres = fuse_send_write(req, file, pos, count, NULL);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
-       if (!err && !nres)
-               err = -EIO;
-       if (!err) {
-               pos += nres;
-               fuse_write_update_size(inode, pos);
-               if (count == PAGE_CACHE_SIZE)
-                       SetPageUptodate(page);
-       }
-       fuse_invalidate_attr(inode);
-       return err ? err : nres;
-}
-
-static int fuse_write_end(struct file *file, struct address_space *mapping,
-                       loff_t pos, unsigned len, unsigned copied,
-                       struct page *page, void *fsdata)
-{
-       struct inode *inode = mapping->host;
-       int res = 0;
-
-       if (copied)
-               res = fuse_buffered_write(file, inode, pos, copied, page);
-
-       unlock_page(page);
-       page_cache_release(page);
-       return res;
-}
-
 static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
                                    struct inode *inode, loff_t pos,
                                    size_t count)
@@ -908,6 +847,8 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
                pagefault_enable();
                flush_dcache_page(page);
 
+               mark_page_accessed(page);
+
                if (!tmp) {
                        unlock_page(page);
                        page_cache_release(page);
@@ -1559,11 +1500,14 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
 
-       if (fc->no_lock) {
+       if (fc->no_flock) {
                err = flock_lock_file_wait(file, fl);
        } else {
+               struct fuse_file *ff = file->private_data;
+
                /* emulate flock with POSIX locks */
                fl->fl_owner = (fl_owner_t) file;
+               ff->flock = true;
                err = fuse_setlk(file, fl, 1);
        }
 
@@ -2201,8 +2145,6 @@ static const struct address_space_operations fuse_file_aops  = {
        .readpage       = fuse_readpage,
        .writepage      = fuse_writepage,
        .launder_page   = fuse_launder_page,
-       .write_begin    = fuse_write_begin,
-       .write_end      = fuse_write_end,
        .readpages      = fuse_readpages,
        .set_page_dirty = __set_page_dirty_nobuffers,
        .bmap           = fuse_bmap,
index c6aa2d4..cf6db0a 100644 (file)
@@ -135,6 +135,9 @@ struct fuse_file {
 
        /** Wait queue head for poll */
        wait_queue_head_t poll_wait;
+
+       /** Has flock been performed on this file? */
+       bool flock:1;
 };
 
 /** One input argument of a request */
@@ -448,7 +451,7 @@ struct fuse_conn {
        /** Is removexattr not implemented by fs? */
        unsigned no_removexattr:1;
 
-       /** Are file locking primitives not implemented by fs? */
+       /** Are posix file locking primitives not implemented by fs? */
        unsigned no_lock:1;
 
        /** Is access not implemented by fs? */
@@ -472,6 +475,9 @@ struct fuse_conn {
        /** Don't apply umask to creation modes */
        unsigned dont_mask:1;
 
+       /** Are BSD file locking primitives not implemented by fs? */
+       unsigned no_flock:1;
+
        /** The number of requests waiting for completion */
        atomic_t num_waiting;
 
index 38f84cd..add96f6 100644 (file)
@@ -71,7 +71,7 @@ struct fuse_mount_data {
        unsigned blksize;
 };
 
-struct fuse_forget_link *fuse_alloc_forget()
+struct fuse_forget_link *fuse_alloc_forget(void)
 {
        return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL);
 }
@@ -809,6 +809,13 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                                fc->async_read = 1;
                        if (!(arg->flags & FUSE_POSIX_LOCKS))
                                fc->no_lock = 1;
+                       if (arg->minor >= 17) {
+                               if (!(arg->flags & FUSE_FLOCK_LOCKS))
+                                       fc->no_flock = 1;
+                       } else {
+                               if (!(arg->flags & FUSE_POSIX_LOCKS))
+                                       fc->no_flock = 1;
+                       }
                        if (arg->flags & FUSE_ATOMIC_O_TRUNC)
                                fc->atomic_o_trunc = 1;
                        if (arg->minor >= 9) {
@@ -823,6 +830,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                } else {
                        ra_pages = fc->max_read / PAGE_CACHE_SIZE;
                        fc->no_lock = 1;
+                       fc->no_flock = 1;
                }
 
                fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
@@ -843,7 +851,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
        arg->minor = FUSE_KERNEL_MINOR_VERSION;
        arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
        arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
-               FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK;
+               FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
+               FUSE_FLOCK_LOCKS;
        req->in.h.opcode = FUSE_INIT;
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(*arg);
index 87b6e04..ec88953 100644 (file)
@@ -491,6 +491,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
                        inode->i_op = &page_symlink_inode_operations;
                        break;
                }
+               lockdep_annotate_inode_mutex_key(inode);
        }
        return inode;
 }
index 73920d5..ec79246 100644 (file)
@@ -848,16 +848,9 @@ struct inode *new_inode(struct super_block *sb)
 }
 EXPORT_SYMBOL(new_inode);
 
-/**
- * unlock_new_inode - clear the I_NEW state and wake up any waiters
- * @inode:     new inode to unlock
- *
- * Called when the inode is fully initialised to clear the new state of the
- * inode and wake up anyone waiting for the inode to finish initialisation.
- */
-void unlock_new_inode(struct inode *inode)
-{
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
+void lockdep_annotate_inode_mutex_key(struct inode *inode)
+{
        if (S_ISDIR(inode->i_mode)) {
                struct file_system_type *type = inode->i_sb->s_type;
 
@@ -873,7 +866,20 @@ void unlock_new_inode(struct inode *inode)
                                          &type->i_mutex_dir_key);
                }
        }
+}
+EXPORT_SYMBOL(lockdep_annotate_inode_mutex_key);
 #endif
+
+/**
+ * unlock_new_inode - clear the I_NEW state and wake up any waiters
+ * @inode:     new inode to unlock
+ *
+ * Called when the inode is fully initialised to clear the new state of the
+ * inode and wake up anyone waiting for the inode to finish initialisation.
+ */
+void unlock_new_inode(struct inode *inode)
+{
+       lockdep_annotate_inode_mutex_key(inode);
        spin_lock(&inode->i_lock);
        WARN_ON(!(inode->i_state & I_NEW));
        inode->i_state &= ~I_NEW;
index adcf92d..7971f37 100644 (file)
@@ -68,7 +68,7 @@ int jfs_umount(struct super_block *sb)
                /*
                 * Wait for outstanding transactions to be written to log:
                 */
-               jfs_flush_journal(log, 1);
+               jfs_flush_journal(log, 2);
 
        /*
         * close fileset inode allocation map (aka fileset inode)
@@ -146,7 +146,7 @@ int jfs_umount_rw(struct super_block *sb)
         *
         * remove file system from log active file system list.
         */
-       jfs_flush_journal(log, 1);
+       jfs_flush_journal(log, 2);
 
        /*
         * Make sure all metadata makes it to disk
index 2826db3..b52bc68 100644 (file)
@@ -727,25 +727,22 @@ static int follow_automount(struct path *path, unsigned flags,
        if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
                return -EISDIR; /* we actually want to stop here */
 
-       /*
-        * We don't want to mount if someone's just doing a stat and they've
-        * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and
-        * appended a '/' to the name.
+       /* We don't want to mount if someone's just doing a stat -
+        * unless they're stat'ing a directory and appended a '/' to
+        * the name.
+        *
+        * We do, however, want to mount if someone wants to open or
+        * create a file of any type under the mountpoint, wants to
+        * traverse through the mountpoint or wants to open the
+        * mounted directory.  Also, autofs may mark negative dentries
+        * as being automount points.  These will need the attentions
+        * of the daemon to instantiate them before they can be used.
         */
-       if (!(flags & LOOKUP_FOLLOW)) {
-               /* We do, however, want to mount if someone wants to open or
-                * create a file of any type under the mountpoint, wants to
-                * traverse through the mountpoint or wants to open the mounted
-                * directory.
-                * Also, autofs may mark negative dentries as being automount
-                * points.  These will need the attentions of the daemon to
-                * instantiate them before they can be used.
-                */
-               if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
-                            LOOKUP_OPEN | LOOKUP_CREATE)) &&
-                   path->dentry->d_inode)
-                       return -EISDIR;
-       }
+       if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
+                    LOOKUP_OPEN | LOOKUP_CREATE)) &&
+           path->dentry->d_inode)
+               return -EISDIR;
+
        current->total_link_count++;
        if (current->total_link_count >= 40)
                return -ELOOP;
index e56564d..9561c8f 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/namei.h>
 #include <linux/bio.h>         /* struct bio */
 #include <linux/buffer_head.h> /* various write calls */
+#include <linux/prefetch.h>
 
 #include "blocklayout.h"
 
index b257383..07df5f1 100644 (file)
@@ -38,6 +38,7 @@ enum nfs4_callback_opnum {
 struct cb_process_state {
        __be32                  drc_status;
        struct nfs_client       *clp;
+       int                     slotid;
 };
 
 struct cb_compound_hdr_arg {
@@ -166,7 +167,6 @@ extern unsigned nfs4_callback_layoutrecall(
        void *dummy, struct cb_process_state *cps);
 
 extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses);
-extern void nfs4_cb_take_slot(struct nfs_client *clp);
 
 struct cb_devicenotifyitem {
        uint32_t                cbd_notify_type;
index 74780f9..43926ad 100644 (file)
@@ -348,7 +348,7 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
        /* Normal */
        if (likely(args->csa_sequenceid == slot->seq_nr + 1)) {
                slot->seq_nr++;
-               return htonl(NFS4_OK);
+               goto out_ok;
        }
 
        /* Replay */
@@ -367,11 +367,14 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
        /* Wraparound */
        if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
                slot->seq_nr = 1;
-               return htonl(NFS4_OK);
+               goto out_ok;
        }
 
        /* Misordered request */
        return htonl(NFS4ERR_SEQ_MISORDERED);
+out_ok:
+       tbl->highest_used_slotid = args->csa_slotid;
+       return htonl(NFS4_OK);
 }
 
 /*
@@ -433,26 +436,37 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
                              struct cb_sequenceres *res,
                              struct cb_process_state *cps)
 {
+       struct nfs4_slot_table *tbl;
        struct nfs_client *clp;
        int i;
        __be32 status = htonl(NFS4ERR_BADSESSION);
 
-       cps->clp = NULL;
-
        clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid);
        if (clp == NULL)
                goto out;
 
+       tbl = &clp->cl_session->bc_slot_table;
+
+       spin_lock(&tbl->slot_tbl_lock);
        /* state manager is resetting the session */
        if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) {
-               status = NFS4ERR_DELAY;
+               spin_unlock(&tbl->slot_tbl_lock);
+               status = htonl(NFS4ERR_DELAY);
+               /* Return NFS4ERR_BADSESSION if we're draining the session
+                * in order to reset it.
+                */
+               if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
+                       status = htonl(NFS4ERR_BADSESSION);
                goto out;
        }
 
        status = validate_seqid(&clp->cl_session->bc_slot_table, args);
+       spin_unlock(&tbl->slot_tbl_lock);
        if (status)
                goto out;
 
+       cps->slotid = args->csa_slotid;
+
        /*
         * Check for pending referring calls.  If a match is found, a
         * related callback was received before the response to the original
@@ -469,7 +483,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
        res->csr_slotid = args->csa_slotid;
        res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
        res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
-       nfs4_cb_take_slot(clp);
 
 out:
        cps->clp = clp; /* put in nfs4_callback_compound */
index c6c86a7..918ad64 100644 (file)
@@ -754,26 +754,15 @@ static void nfs4_callback_free_slot(struct nfs4_session *session)
         * Let the state manager know callback processing done.
         * A single slot, so highest used slotid is either 0 or -1
         */
-       tbl->highest_used_slotid--;
+       tbl->highest_used_slotid = -1;
        nfs4_check_drain_bc_complete(session);
        spin_unlock(&tbl->slot_tbl_lock);
 }
 
-static void nfs4_cb_free_slot(struct nfs_client *clp)
+static void nfs4_cb_free_slot(struct cb_process_state *cps)
 {
-       if (clp && clp->cl_session)
-               nfs4_callback_free_slot(clp->cl_session);
-}
-
-/* A single slot, so highest used slotid is either 0 or -1 */
-void nfs4_cb_take_slot(struct nfs_client *clp)
-{
-       struct nfs4_slot_table *tbl = &clp->cl_session->bc_slot_table;
-
-       spin_lock(&tbl->slot_tbl_lock);
-       tbl->highest_used_slotid++;
-       BUG_ON(tbl->highest_used_slotid != 0);
-       spin_unlock(&tbl->slot_tbl_lock);
+       if (cps->slotid != -1)
+               nfs4_callback_free_slot(cps->clp->cl_session);
 }
 
 #else /* CONFIG_NFS_V4_1 */
@@ -784,7 +773,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
        return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
 }
 
-static void nfs4_cb_free_slot(struct nfs_client *clp)
+static void nfs4_cb_free_slot(struct cb_process_state *cps)
 {
 }
 #endif /* CONFIG_NFS_V4_1 */
@@ -866,6 +855,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
        struct cb_process_state cps = {
                .drc_status = 0,
                .clp = NULL,
+               .slotid = -1,
        };
        unsigned int nops = 0;
 
@@ -906,7 +896,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
 
        *hdr_res.status = status;
        *hdr_res.nops = htonl(nops);
-       nfs4_cb_free_slot(cps.clp);
+       nfs4_cb_free_slot(&cps);
        nfs_put_client(cps.clp);
        dprintk("%s: done, status = %u\n", __func__, ntohl(status));
        return rpc_success;
index 9383ca7..d0cda12 100644 (file)
@@ -479,7 +479,6 @@ static int _io_check(struct objio_state *ios, bool is_write)
        for (i = 0; i <  ios->numdevs; i++) {
                struct osd_sense_info osi;
                struct osd_request *or = ios->per_dev[i].or;
-               unsigned dev;
                int ret;
 
                if (!or)
@@ -500,9 +499,8 @@ static int _io_check(struct objio_state *ios, bool is_write)
 
                        continue; /* we recovered */
                }
-               dev = ios->per_dev[i].dev;
-               objlayout_io_set_result(&ios->ol_state, dev,
-                                       &ios->layout->comps[dev].oc_object_id,
+               objlayout_io_set_result(&ios->ol_state, i,
+                                       &ios->layout->comps[i].oc_object_id,
                                        osd_pri_2_pnfs_err(osi.osd_err_pri),
                                        ios->per_dev[i].offset,
                                        ios->per_dev[i].length,
@@ -589,22 +587,19 @@ static void _calc_stripe_info(struct objio_state *ios, u64 file_offset,
 }
 
 static int _add_stripe_unit(struct objio_state *ios,  unsigned *cur_pg,
-               unsigned pgbase, struct _objio_per_comp *per_dev, int cur_len,
+               unsigned pgbase, struct _objio_per_comp *per_dev, int len,
                gfp_t gfp_flags)
 {
        unsigned pg = *cur_pg;
+       int cur_len = len;
        struct request_queue *q =
                        osd_request_queue(_io_od(ios, per_dev->dev));
 
-       per_dev->length += cur_len;
-
        if (per_dev->bio == NULL) {
-               unsigned stripes = ios->layout->num_comps /
-                                                    ios->layout->mirrors_p1;
-               unsigned pages_in_stripe = stripes *
+               unsigned pages_in_stripe = ios->layout->group_width *
                                      (ios->layout->stripe_unit / PAGE_SIZE);
                unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) /
-                                   stripes;
+                                   ios->layout->group_width;
 
                if (BIO_MAX_PAGES_KMALLOC < bio_size)
                        bio_size = BIO_MAX_PAGES_KMALLOC;
@@ -632,6 +627,7 @@ static int _add_stripe_unit(struct objio_state *ios,  unsigned *cur_pg,
        }
        BUG_ON(cur_len);
 
+       per_dev->length += len;
        *cur_pg = pg;
        return 0;
 }
@@ -650,7 +646,7 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,
        int ret = 0;
 
        while (length) {
-               struct _objio_per_comp *per_dev = &ios->per_dev[dev];
+               struct _objio_per_comp *per_dev = &ios->per_dev[dev - first_dev];
                unsigned cur_len, page_off = 0;
 
                if (!per_dev->length) {
@@ -670,8 +666,8 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,
                                cur_len = stripe_unit;
                        }
 
-                       if (max_comp < dev)
-                               max_comp = dev;
+                       if (max_comp < dev - first_dev)
+                               max_comp = dev - first_dev;
                } else {
                        cur_len = stripe_unit;
                }
@@ -806,7 +802,7 @@ static int _read_mirrors(struct objio_state *ios, unsigned cur_comp)
        struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp];
        unsigned dev = per_dev->dev;
        struct pnfs_osd_object_cred *cred =
-                       &ios->layout->comps[dev];
+                       &ios->layout->comps[cur_comp];
        struct osd_obj_id obj = {
                .partition = cred->oc_object_id.oid_partition_id,
                .id = cred->oc_object_id.oid_object_id,
@@ -904,7 +900,7 @@ static int _write_mirrors(struct objio_state *ios, unsigned cur_comp)
        for (; cur_comp < last_comp; ++cur_comp, ++dev) {
                struct osd_request *or = NULL;
                struct pnfs_osd_object_cred *cred =
-                                       &ios->layout->comps[dev];
+                                       &ios->layout->comps[cur_comp];
                struct osd_obj_id obj = {
                        .partition = cred->oc_object_id.oid_partition_id,
                        .id = cred->oc_object_id.oid_object_id,
index 16fc758..b3918f7 100644 (file)
@@ -170,6 +170,9 @@ int pnfs_osd_xdr_decode_layout_map(struct pnfs_osd_layout *layout,
        p = _osd_xdr_decode_data_map(p, &layout->olo_map);
        layout->olo_comps_index = be32_to_cpup(p++);
        layout->olo_num_comps = be32_to_cpup(p++);
+       dprintk("%s: olo_comps_index=%d olo_num_comps=%d\n", __func__,
+               layout->olo_comps_index, layout->olo_num_comps);
+
        iter->total_comps = layout->olo_num_comps;
        return 0;
 }
index 45174b5..feb361e 100644 (file)
@@ -335,9 +335,9 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 #define DBGKEY(key)  ((char *)(key))
 #define DBGKEY1(key) ((char *)(key))
 
-#define ubifs_dbg_msg(fmt, ...) do {               \
-       if (0)                                     \
-               pr_debug(fmt "\n", ##__VA_ARGS__); \
+#define ubifs_dbg_msg(fmt, ...) do {                        \
+       if (0)                                              \
+               printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__); \
 } while (0)
 
 #define dbg_dump_stack()
index 75bb316..427a4e8 100644 (file)
 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #
 
-ccflags-y := -I$(src) -I$(src)/linux-2.6
-ccflags-$(CONFIG_XFS_DEBUG) += -g
+ccflags-y += -I$(src)                  # needed for trace events
 
-XFS_LINUX := linux-2.6
+ccflags-$(CONFIG_XFS_DEBUG) += -g
 
 obj-$(CONFIG_XFS_FS)           += xfs.o
 
-xfs-y                          += linux-2.6/xfs_trace.o
-
-xfs-$(CONFIG_XFS_QUOTA)                += $(addprefix quota/, \
-                                  xfs_dquot.o \
-                                  xfs_dquot_item.o \
-                                  xfs_trans_dquot.o \
-                                  xfs_qm_syscalls.o \
-                                  xfs_qm_bhv.o \
-                                  xfs_qm.o)
-xfs-$(CONFIG_XFS_QUOTA)                += linux-2.6/xfs_quotaops.o
-
-ifeq ($(CONFIG_XFS_QUOTA),y)
-xfs-$(CONFIG_PROC_FS)          += quota/xfs_qm_stats.o
-endif
-
-xfs-$(CONFIG_XFS_RT)           += xfs_rtalloc.o
-xfs-$(CONFIG_XFS_POSIX_ACL)    += $(XFS_LINUX)/xfs_acl.o
-xfs-$(CONFIG_PROC_FS)          += $(XFS_LINUX)/xfs_stats.o
-xfs-$(CONFIG_SYSCTL)           += $(XFS_LINUX)/xfs_sysctl.o
-xfs-$(CONFIG_COMPAT)           += $(XFS_LINUX)/xfs_ioctl32.o
+# this one should be compiled first, as the tracing macros can easily blow up
+xfs-y                          += xfs_trace.o
 
+# highlevel code
+xfs-y                          += xfs_aops.o \
+                                  xfs_bit.o \
+                                  xfs_buf.o \
+                                  xfs_dfrag.o \
+                                  xfs_discard.o \
+                                  xfs_error.o \
+                                  xfs_export.o \
+                                  xfs_file.o \
+                                  xfs_filestream.o \
+                                  xfs_fsops.o \
+                                  xfs_fs_subr.o \
+                                  xfs_globals.o \
+                                  xfs_iget.o \
+                                  xfs_ioctl.o \
+                                  xfs_iomap.o \
+                                  xfs_iops.o \
+                                  xfs_itable.o \
+                                  xfs_message.o \
+                                  xfs_mru_cache.o \
+                                  xfs_super.o \
+                                  xfs_sync.o \
+                                  xfs_xattr.o \
+                                  xfs_rename.o \
+                                  xfs_rw.o \
+                                  xfs_utils.o \
+                                  xfs_vnodeops.o \
+                                  kmem.o \
+                                  uuid.o
 
+# code shared with libxfs
 xfs-y                          += xfs_alloc.o \
                                   xfs_alloc_btree.o \
                                   xfs_attr.o \
                                   xfs_attr_leaf.o \
-                                  xfs_bit.o \
                                   xfs_bmap.o \
                                   xfs_bmap_btree.o \
                                   xfs_btree.o \
-                                  xfs_buf_item.o \
                                   xfs_da_btree.o \
                                   xfs_dir2.o \
                                   xfs_dir2_block.o \
@@ -61,49 +70,37 @@ xfs-y                               += xfs_alloc.o \
                                   xfs_dir2_leaf.o \
                                   xfs_dir2_node.o \
                                   xfs_dir2_sf.o \
-                                  xfs_error.o \
-                                  xfs_extfree_item.o \
-                                  xfs_filestream.o \
-                                  xfs_fsops.o \
                                   xfs_ialloc.o \
                                   xfs_ialloc_btree.o \
-                                  xfs_iget.o \
                                   xfs_inode.o \
-                                  xfs_inode_item.o \
-                                  xfs_iomap.o \
-                                  xfs_itable.o \
-                                  xfs_dfrag.o \
-                                  xfs_log.o \
-                                  xfs_log_cil.o \
                                   xfs_log_recover.o \
                                   xfs_mount.o \
-                                  xfs_mru_cache.o \
-                                  xfs_rename.o \
-                                  xfs_trans.o \
+                                  xfs_trans.o
+
+# low-level transaction/log code
+xfs-y                          += xfs_log.o \
+                                  xfs_log_cil.o \
+                                  xfs_buf_item.o \
+                                  xfs_extfree_item.o \
+                                  xfs_inode_item.o \
                                   xfs_trans_ail.o \
                                   xfs_trans_buf.o \
                                   xfs_trans_extfree.o \
                                   xfs_trans_inode.o \
-                                  xfs_utils.o \
-                                  xfs_vnodeops.o \
-                                  xfs_rw.o
-
-# Objects in linux/
-xfs-y                          += $(addprefix $(XFS_LINUX)/, \
-                                  kmem.o \
-                                  xfs_aops.o \
-                                  xfs_buf.o \
-                                  xfs_discard.o \
-                                  xfs_export.o \
-                                  xfs_file.o \
-                                  xfs_fs_subr.o \
-                                  xfs_globals.o \
-                                  xfs_ioctl.o \
-                                  xfs_iops.o \
-                                  xfs_message.o \
-                                  xfs_super.o \
-                                  xfs_sync.o \
-                                  xfs_xattr.o)
 
-# Objects in support/
-xfs-y                          += support/uuid.o
+# optional features
+xfs-$(CONFIG_XFS_QUOTA)                += xfs_dquot.o \
+                                  xfs_dquot_item.o \
+                                  xfs_trans_dquot.o \
+                                  xfs_qm_syscalls.o \
+                                  xfs_qm_bhv.o \
+                                  xfs_qm.o \
+                                  xfs_quotaops.o
+ifeq ($(CONFIG_XFS_QUOTA),y)
+xfs-$(CONFIG_PROC_FS)          += xfs_qm_stats.o
+endif
+xfs-$(CONFIG_XFS_RT)           += xfs_rtalloc.o
+xfs-$(CONFIG_XFS_POSIX_ACL)    += xfs_acl.o
+xfs-$(CONFIG_PROC_FS)          += xfs_stats.o
+xfs-$(CONFIG_SYSCTL)           += xfs_sysctl.o
+xfs-$(CONFIG_COMPAT)           += xfs_ioctl32.o
similarity index 100%
rename from fs/xfs/linux-2.6/kmem.c
rename to fs/xfs/kmem.c
similarity index 100%
rename from fs/xfs/linux-2.6/kmem.h
rename to fs/xfs/kmem.h
similarity index 100%
rename from fs/xfs/linux-2.6/mrlock.h
rename to fs/xfs/mrlock.h
similarity index 100%
rename from fs/xfs/linux-2.6/time.h
rename to fs/xfs/time.h
similarity index 100%
rename from fs/xfs/support/uuid.c
rename to fs/xfs/uuid.c
similarity index 100%
rename from fs/xfs/support/uuid.h
rename to fs/xfs/uuid.h
index 53ec3ea..d8b11b7 100644 (file)
@@ -24,5 +24,6 @@
 #define XFS_BUF_LOCK_TRACKING 1
 #endif
 
-#include <linux-2.6/xfs_linux.h>
+#include "xfs_linux.h"
+
 #endif /* __XFS_H__ */
similarity index 100%
rename from fs/xfs/linux-2.6/xfs_acl.c
rename to fs/xfs/xfs_acl.c
similarity index 100%
rename from fs/xfs/linux-2.6/xfs_buf.c
rename to fs/xfs/xfs_buf.c
similarity index 100%
rename from fs/xfs/linux-2.6/xfs_buf.h
rename to fs/xfs/xfs_buf.h
similarity index 100%
rename from fs/xfs/quota/xfs_dquot.c
rename to fs/xfs/xfs_dquot.c
similarity index 100%
rename from fs/xfs/quota/xfs_dquot.h
rename to fs/xfs/xfs_dquot.h
similarity index 99%
rename from fs/xfs/linux-2.6/xfs_iops.c
rename to fs/xfs/xfs_iops.c
index b9c172b..673704f 100644 (file)
@@ -70,9 +70,8 @@ xfs_synchronize_times(
 }
 
 /*
- * If the linux inode is valid, mark it dirty.
- * Used when committing a dirty inode into a transaction so that
- * the inode will get written back by the linux code
+ * If the linux inode is valid, mark it dirty, else mark the dirty state
+ * in the XFS inode to make sure we pick it up when reclaiming the inode.
  */
 void
 xfs_mark_inode_dirty_sync(
@@ -82,6 +81,10 @@ xfs_mark_inode_dirty_sync(
 
        if (!(inode->i_state & (I_WILL_FREE|I_FREEING)))
                mark_inode_dirty_sync(inode);
+       else {
+               barrier();
+               ip->i_update_core = 1;
+       }
 }
 
 void
@@ -92,6 +95,11 @@ xfs_mark_inode_dirty(
 
        if (!(inode->i_state & (I_WILL_FREE|I_FREEING)))
                mark_inode_dirty(inode);
+       else {
+               barrier();
+               ip->i_update_core = 1;
+       }
+
 }
 
 /*
similarity index 96%
rename from fs/xfs/linux-2.6/xfs_linux.h
rename to fs/xfs/xfs_linux.h
index d42f814..1e8a45e 100644 (file)
 # define XFS_BIG_INUMS 0
 #endif
 
-#include <xfs_types.h>
+#include "xfs_types.h"
 
-#include <kmem.h>
-#include <mrlock.h>
-#include <time.h>
-
-#include <support/uuid.h>
+#include "kmem.h"
+#include "mrlock.h"
+#include "time.h"
+#include "uuid.h"
 
 #include <linux/semaphore.h>
 #include <linux/mm.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
-#include <xfs_vnode.h>
-#include <xfs_stats.h>
-#include <xfs_sysctl.h>
-#include <xfs_iops.h>
-#include <xfs_aops.h>
-#include <xfs_super.h>
-#include <xfs_buf.h>
-#include <xfs_message.h>
+#include "xfs_vnode.h"
+#include "xfs_stats.h"
+#include "xfs_sysctl.h"
+#include "xfs_iops.h"
+#include "xfs_aops.h"
+#include "xfs_super.h"
+#include "xfs_buf.h"
+#include "xfs_message.h"
 
 #ifdef __BIG_ENDIAN
 #define XFS_NATIVE_HOST 1
similarity index 100%
rename from fs/xfs/quota/xfs_qm.c
rename to fs/xfs/xfs_qm.c
similarity index 100%
rename from fs/xfs/quota/xfs_qm.h
rename to fs/xfs/xfs_qm.h
similarity index 99%
rename from fs/xfs/linux-2.6/xfs_quotaops.c
rename to fs/xfs/xfs_quotaops.c
index 29b9d64..7e76f53 100644 (file)
@@ -25,7 +25,7 @@
 #include "xfs_trans.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_inode.h"
-#include "quota/xfs_qm.h"
+#include "xfs_qm.h"
 #include <linux/quota.h>
 
 
similarity index 98%
rename from fs/xfs/linux-2.6/xfs_super.c
rename to fs/xfs/xfs_super.c
index 9a72dda..2366c54 100644 (file)
@@ -356,6 +356,8 @@ xfs_parseargs(
                        mp->m_flags |= XFS_MOUNT_DELAYLOG;
                } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {
                        mp->m_flags &= ~XFS_MOUNT_DELAYLOG;
+                       xfs_warn(mp,
+       "nodelaylog is deprecated and will be removed in Linux 3.3");
                } else if (!strcmp(this_char, MNTOPT_DISCARD)) {
                        mp->m_flags |= XFS_MOUNT_DISCARD;
                } else if (!strcmp(this_char, MNTOPT_NODISCARD)) {
@@ -877,33 +879,17 @@ xfs_log_inode(
        struct xfs_trans        *tp;
        int                     error;
 
-       xfs_iunlock(ip, XFS_ILOCK_SHARED);
        tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
        error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0);
-
        if (error) {
                xfs_trans_cancel(tp, 0);
-               /* we need to return with the lock hold shared */
-               xfs_ilock(ip, XFS_ILOCK_SHARED);
                return error;
        }
 
        xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-       /*
-        * Note - it's possible that we might have pushed ourselves out of the
-        * way during trans_reserve which would flush the inode.  But there's
-        * no guarantee that the inode buffer has actually gone out yet (it's
-        * delwri).  Plus the buffer could be pinned anyway if it's part of
-        * an inode in another recent transaction.  So we play it safe and
-        * fire off the transaction anyway.
-        */
-       xfs_trans_ijoin(tp, ip);
+       xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       error = xfs_trans_commit(tp, 0);
-       xfs_ilock_demote(ip, XFS_ILOCK_EXCL);
-
-       return error;
+       return xfs_trans_commit(tp, 0);
 }
 
 STATIC int
@@ -918,7 +904,9 @@ xfs_fs_write_inode(
        trace_xfs_write_inode(ip);
 
        if (XFS_FORCED_SHUTDOWN(mp))
-               return XFS_ERROR(EIO);
+               return -XFS_ERROR(EIO);
+       if (!ip->i_update_core)
+               return 0;
 
        if (wbc->sync_mode == WB_SYNC_ALL) {
                /*
@@ -929,12 +917,10 @@ xfs_fs_write_inode(
                 * of synchronous log foces dramatically.
                 */
                xfs_ioend_wait(ip);
-               xfs_ilock(ip, XFS_ILOCK_SHARED);
-               if (ip->i_update_core) {
-                       error = xfs_log_inode(ip);
-                       if (error)
-                               goto out_unlock;
-               }
+               error = xfs_log_inode(ip);
+               if (error)
+                       goto out;
+               return 0;
        } else {
                /*
                 * We make this non-blocking if the inode is contended, return
similarity index 96%
rename from fs/xfs/linux-2.6/xfs_trace.c
rename to fs/xfs/xfs_trace.c
index 88d25d4..9010ce8 100644 (file)
@@ -43,8 +43,8 @@
 #include "xfs_quota.h"
 #include "xfs_iomap.h"
 #include "xfs_aops.h"
-#include "quota/xfs_dquot_item.h"
-#include "quota/xfs_dquot.h"
+#include "xfs_dquot_item.h"
+#include "xfs_dquot.h"
 #include "xfs_log_recover.h"
 #include "xfs_inode_item.h"
 
index fb2d63f..aea9e45 100644 (file)
@@ -39,7 +39,7 @@
 })
 
 #define __page_to_pfn(pg)                                              \
-({     struct page *__pg = (pg);                                       \
+({     const struct page *__pg = (pg);                                 \
        struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg));     \
        (unsigned long)(__pg - __pgdat->node_mem_map) +                 \
         __pgdat->node_start_pfn;                                       \
@@ -57,7 +57,7 @@
  * section[i].section_mem_map == mem_map's address - start_pfn;
  */
 #define __page_to_pfn(pg)                                      \
-({     struct page *__pg = (pg);                               \
+({     const struct page *__pg = (pg);                         \
        int __sec = page_to_section(__pg);                      \
        (unsigned long)(__pg - __section_mem_map_addr(__nr_to_section(__sec))); \
 })
index 4f76959..f4c38d8 100644 (file)
@@ -143,7 +143,7 @@ __SYSCALL(__NR_pivot_root, sys_pivot_root)
 
 /* fs/nfsctl.c */
 #define __NR_nfsservctl 42
-__SC_COMP(__NR_nfsservctl, sys_nfsservctl, compat_sys_nfsservctl)
+__SYSCALL(__NR_nfsservctl, sys_ni_syscall)
 
 /* fs/open.c */
 #define __NR3264_statfs 43
index 6395692..32f0076 100644 (file)
@@ -125,7 +125,11 @@ enum rq_flag_bits {
        __REQ_SYNC,             /* request is sync (sync write or read) */
        __REQ_META,             /* metadata io request */
        __REQ_DISCARD,          /* request to discard sectors */
+       __REQ_SECURE,           /* secure discard (used with __REQ_DISCARD) */
+
        __REQ_NOIDLE,           /* don't anticipate more IO after this one */
+       __REQ_FUA,              /* forced unit access */
+       __REQ_FLUSH,            /* request for cache flush */
 
        /* bio only flags */
        __REQ_RAHEAD,           /* read ahead, can fail anytime */
@@ -135,7 +139,6 @@ enum rq_flag_bits {
        /* request only flags */
        __REQ_SORTED,           /* elevator knows about this request */
        __REQ_SOFTBARRIER,      /* may not be passed by ioscheduler */
-       __REQ_FUA,              /* forced unit access */
        __REQ_NOMERGE,          /* don't touch this for merging */
        __REQ_STARTED,          /* drive already may have started this one */
        __REQ_DONTPREP,         /* don't call prep for this one */
@@ -146,11 +149,9 @@ enum rq_flag_bits {
        __REQ_PREEMPT,          /* set for "ide_preempt" requests */
        __REQ_ALLOCED,          /* request came from our alloc pool */
        __REQ_COPY_USER,        /* contains copies of user pages */
-       __REQ_FLUSH,            /* request for cache flush */
        __REQ_FLUSH_SEQ,        /* request for flush sequence */
        __REQ_IO_STAT,          /* account I/O stat */
        __REQ_MIXED_MERGE,      /* merge of different types, fail separately */
-       __REQ_SECURE,           /* secure discard (used with __REQ_DISCARD) */
        __REQ_NR_BITS,          /* stops here */
 };
 
index 0e67c45..84b15d5 100644 (file)
@@ -30,6 +30,7 @@ struct request_pm_state;
 struct blk_trace;
 struct request;
 struct sg_io_hdr;
+struct bsg_job;
 
 #define BLKDEV_MIN_RQ  4
 #define BLKDEV_MAX_RQ  128     /* Default maximum */
@@ -117,6 +118,7 @@ struct request {
                struct {
                        unsigned int            seq;
                        struct list_head        list;
+                       rq_end_io_fn            *saved_end_io;
                } flush;
        };
 
@@ -209,6 +211,7 @@ typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *,
 typedef void (softirq_done_fn)(struct request *);
 typedef int (dma_drain_needed_fn)(struct request *);
 typedef int (lld_busy_fn) (struct request_queue *q);
+typedef int (bsg_job_fn) (struct bsg_job *);
 
 enum blk_eh_timer_return {
        BLK_EH_NOT_HANDLED,
@@ -375,6 +378,8 @@ struct request_queue {
        struct mutex            sysfs_lock;
 
 #if defined(CONFIG_BLK_DEV_BSG)
+       bsg_job_fn              *bsg_job_fn;
+       int                     bsg_job_size;
        struct bsg_class_device bsg_dev;
 #endif
 
index 8c7c2de..8e9e4bc 100644 (file)
@@ -14,7 +14,7 @@
 enum blktrace_cat {
        BLK_TC_READ     = 1 << 0,       /* reads */
        BLK_TC_WRITE    = 1 << 1,       /* writes */
-       BLK_TC_BARRIER  = 1 << 2,       /* barrier */
+       BLK_TC_FLUSH    = 1 << 2,       /* flush */
        BLK_TC_SYNC     = 1 << 3,       /* sync IO */
        BLK_TC_SYNCIO   = BLK_TC_SYNC,
        BLK_TC_QUEUE    = 1 << 4,       /* queueing/merging */
@@ -28,8 +28,9 @@ enum blktrace_cat {
        BLK_TC_META     = 1 << 12,      /* metadata */
        BLK_TC_DISCARD  = 1 << 13,      /* discard requests */
        BLK_TC_DRV_DATA = 1 << 14,      /* binary per-driver data */
+       BLK_TC_FUA      = 1 << 15,      /* fua requests */
 
-       BLK_TC_END      = 1 << 15,      /* only 16-bits, reminder */
+       BLK_TC_END      = 1 << 15,      /* we've run out of bits! */
 };
 
 #define BLK_TC_SHIFT           (16)
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
new file mode 100644 (file)
index 0000000..f55ab8c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  BSG helper library
+ *
+ *  Copyright (C) 2008   James Smart, Emulex Corporation
+ *  Copyright (C) 2011   Red Hat, Inc.  All rights reserved.
+ *  Copyright (C) 2011   Mike Christie
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef _BLK_BSG_
+#define _BLK_BSG_
+
+#include <linux/blkdev.h>
+
+struct request;
+struct device;
+struct scatterlist;
+struct request_queue;
+
+struct bsg_buffer {
+       unsigned int payload_len;
+       int sg_cnt;
+       struct scatterlist *sg_list;
+};
+
+struct bsg_job {
+       struct device *dev;
+       struct request *req;
+
+       /* Transport/driver specific request/reply structs */
+       void *request;
+       void *reply;
+
+       unsigned int request_len;
+       unsigned int reply_len;
+       /*
+        * On entry : reply_len indicates the buffer size allocated for
+        * the reply.
+        *
+        * Upon completion : the message handler must set reply_len
+        *  to indicates the size of the reply to be returned to the
+        *  caller.
+        */
+
+       /* DMA payloads for the request/response */
+       struct bsg_buffer request_payload;
+       struct bsg_buffer reply_payload;
+
+       void *dd_data;          /* Used for driver-specific storage */
+};
+
+void bsg_job_done(struct bsg_job *job, int result,
+                 unsigned int reply_payload_rcv_len);
+int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name,
+                   bsg_job_fn *job_fn, int dd_job_size);
+void bsg_request_fn(struct request_queue *q);
+void bsg_remove_queue(struct request_queue *q);
+void bsg_goose_queue(struct request_queue *q);
+
+#endif
index 8779405..c6e7523 100644 (file)
@@ -438,7 +438,6 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
                                 struct compat_timespec __user *tsp,
                                 const compat_sigset_t __user *sigmask,
                                 compat_size_t sigsetsize);
-asmlinkage long compat_sys_nfsservctl(int cmd, void *notused, void *notused2);
 asmlinkage long compat_sys_signalfd4(int ufd,
                                     const compat_sigset_t __user *sigmask,
                                     compat_size_t sigsetsize, int flags);
index 0c69ad8..3c9c54f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     connector.h
  * 
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004-2005 Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  * 
  * This program is free software; you can redistribute it and/or modify
index 178cdb4..c2bd68f 100644 (file)
@@ -2318,6 +2318,11 @@ extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*te
 extern struct inode * iget_locked(struct super_block *, unsigned long);
 extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *);
 extern int insert_inode_locked(struct inode *);
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+extern void lockdep_annotate_inode_mutex_key(struct inode *inode);
+#else
+static inline void lockdep_annotate_inode_mutex_key(struct inode *inode) { };
+#endif
 extern void unlock_new_inode(struct inode *);
 extern unsigned int get_next_ino(void);
 
index d464de5..464cff5 100644 (file)
@@ -47,6 +47,9 @@
  *  - FUSE_IOCTL_UNRESTRICTED shall now return with array of 'struct
  *    fuse_ioctl_iovec' instead of ambiguous 'struct iovec'
  *  - add FUSE_IOCTL_32BIT flag
+ *
+ * 7.17
+ *  - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK
  */
 
 #ifndef _LINUX_FUSE_H
@@ -78,7 +81,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 16
+#define FUSE_KERNEL_MINOR_VERSION 17
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -153,8 +156,10 @@ struct fuse_file_lock {
 /**
  * INIT request/reply flags
  *
+ * FUSE_POSIX_LOCKS: remote locking for POSIX file locks
  * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
  * FUSE_DONT_MASK: don't apply umask to file mode on create operations
+ * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks
  */
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
@@ -163,6 +168,7 @@ struct fuse_file_lock {
 #define FUSE_EXPORT_SUPPORT    (1 << 4)
 #define FUSE_BIG_WRITES                (1 << 5)
 #define FUSE_DONT_MASK         (1 << 6)
+#define FUSE_FLOCK_LOCKS       (1 << 10)
 
 /**
  * CUSE INIT request/reply flags
@@ -175,6 +181,7 @@ struct fuse_file_lock {
  * Release flags
  */
 #define FUSE_RELEASE_FLUSH     (1 << 0)
+#define FUSE_RELEASE_FLOCK_UNLOCK      (1 << 1)
 
 /**
  * Getattr flags
index 06d25c1..b80506b 100644 (file)
@@ -63,7 +63,7 @@ static inline u32 hash_32(u32 val, unsigned int bits)
        return hash >> (32 - bits);
 }
 
-static inline unsigned long hash_ptr(void *ptr, unsigned int bits)
+static inline unsigned long hash_ptr(const void *ptr, unsigned int bits)
 {
        return hash_long((unsigned long)ptr, bits);
 }
index 87a06f3..5951730 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/errno.h>
 #include <linux/topology.h>
 #include <linux/wait.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <asm/ptrace.h>
@@ -547,7 +548,15 @@ static inline struct msi_desc *irq_data_get_msi(struct irq_data *d)
        return d->msi_desc;
 }
 
-int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node);
+int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
+               struct module *owner);
+
+static inline int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt,
+               int node)
+{
+       return __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE);
+}
+
 void irq_free_descs(unsigned int irq, unsigned int cnt);
 int irq_reserve_irqs(unsigned int from, unsigned int cnt);
 
index 2d921b3..150134a 100644 (file)
@@ -66,6 +66,7 @@ struct irq_desc {
 #ifdef CONFIG_PROC_FS
        struct proc_dir_entry   *dir;
 #endif
+       struct module           *owner;
        const char              *name;
 } ____cacheline_internodealigned_in_smp;
 
index 66c194e..683d698 100644 (file)
@@ -64,7 +64,6 @@ struct loop_device {
 
        struct request_queue    *lo_queue;
        struct gendisk          *lo_disk;
-       struct list_head        lo_list;
 };
 
 #endif /* __KERNEL__ */
@@ -161,4 +160,8 @@ int loop_unregister_transfer(int number);
 #define LOOP_CHANGE_FD         0x4C06
 #define LOOP_SET_CAPACITY      0x4C07
 
+/* /dev/loop-control interface */
+#define LOOP_CTL_ADD           0x4C80
+#define LOOP_CTL_REMOVE                0x4C81
+#define LOOP_CTL_GET_FREE      0x4C82
 #endif
index 18fd130..c309b1e 100644 (file)
@@ -40,6 +40,7 @@
 #define BTRFS_MINOR            234
 #define AUTOFS_MINOR           235
 #define MAPPER_CTRL_MINOR      236
+#define LOOP_CTRL_MINOR                237
 #define MISC_DYNAMIC_MINOR     255
 
 struct device;
index fd599f4..7438071 100644 (file)
@@ -685,7 +685,7 @@ static inline void set_page_section(struct page *page, unsigned long section)
        page->flags |= (section & SECTIONS_MASK) << SECTIONS_PGSHIFT;
 }
 
-static inline unsigned long page_to_section(struct page *page)
+static inline unsigned long page_to_section(const struct page *page)
 {
        return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
 }
@@ -720,7 +720,7 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
 
 static __always_inline void *lowmem_page_address(const struct page *page)
 {
-       return __va(PFN_PHYS(page_to_pfn((struct page *)page)));
+       return __va(PFN_PHYS(page_to_pfn(page)));
 }
 
 #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
@@ -737,7 +737,7 @@ static __always_inline void *lowmem_page_address(const struct page *page)
 #endif
 
 #if defined(HASHED_PAGE_VIRTUAL)
-void *page_address(struct page *page);
+void *page_address(const struct page *page);
 void set_page_address(struct page *page, void *virtual);
 void page_address_init(void);
 #endif
index 0f83858..1d09562 100644 (file)
@@ -56,8 +56,6 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_SDR104  4
 #define MMC_TIMING_UHS_DDR50   5
 
-       unsigned char   ddr;                    /* dual data rate used */
-
 #define MMC_SDR_MODE           0
 #define MMC_1_2V_DDR_MODE      1
 #define MMC_1_8V_DDR_MODE      2
index f27893b..8c230cb 100644 (file)
@@ -251,7 +251,8 @@ struct pci_dev {
        u8              revision;       /* PCI revision, low byte of class word */
        u8              hdr_type;       /* PCI header type (`multi' flag masked out) */
        u8              pcie_cap;       /* PCI-E capability offset */
-       u8              pcie_type;      /* PCI-E device/port type */
+       u8              pcie_type:4;    /* PCI-E device/port type */
+       u8              pcie_mpss:3;    /* PCI-E Max Payload Size Supported */
        u8              rom_base_reg;   /* which config register controls the ROM */
        u8              pin;            /* which interrupt pin this device uses */
 
@@ -617,6 +618,16 @@ struct pci_driver {
 /* these external functions are only available when PCI support is enabled */
 #ifdef CONFIG_PCI
 
+extern void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss);
+
+enum pcie_bus_config_types {
+       PCIE_BUS_PERFORMANCE,
+       PCIE_BUS_SAFE,
+       PCIE_BUS_PEER2PEER,
+};
+
+extern enum pcie_bus_config_types pcie_bus_config;
+
 extern struct bus_type pci_bus_type;
 
 /* Do NOT directly access these two variables, unless you are arch specific pci
@@ -796,10 +807,13 @@ int pcix_get_mmrbc(struct pci_dev *dev);
 int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
 int pcie_get_readrq(struct pci_dev *dev);
 int pcie_set_readrq(struct pci_dev *dev, int rq);
+int pcie_get_mps(struct pci_dev *dev);
+int pcie_set_mps(struct pci_dev *dev, int mps);
 int __pci_reset_function(struct pci_dev *dev);
 int pci_reset_function(struct pci_dev *dev);
 void pci_update_resource(struct pci_dev *dev, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
+int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
 
 /* ROM control related routines */
index 245bafd..c816075 100644 (file)
@@ -944,8 +944,10 @@ extern void perf_pmu_unregister(struct pmu *pmu);
 
 extern int perf_num_counters(void);
 extern const char *perf_pmu_name(void);
-extern void __perf_event_task_sched_in(struct task_struct *task);
-extern void __perf_event_task_sched_out(struct task_struct *task, struct task_struct *next);
+extern void __perf_event_task_sched_in(struct task_struct *prev,
+                                      struct task_struct *task);
+extern void __perf_event_task_sched_out(struct task_struct *prev,
+                                       struct task_struct *next);
 extern int perf_event_init_task(struct task_struct *child);
 extern void perf_event_exit_task(struct task_struct *child);
 extern void perf_event_free_task(struct task_struct *task);
@@ -1059,17 +1061,20 @@ perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)
 
 extern struct jump_label_key perf_sched_events;
 
-static inline void perf_event_task_sched_in(struct task_struct *task)
+static inline void perf_event_task_sched_in(struct task_struct *prev,
+                                           struct task_struct *task)
 {
        if (static_branch(&perf_sched_events))
-               __perf_event_task_sched_in(task);
+               __perf_event_task_sched_in(prev, task);
 }
 
-static inline void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next)
+static inline void perf_event_task_sched_out(struct task_struct *prev,
+                                            struct task_struct *next)
 {
        perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, NULL, 0);
 
-       __perf_event_task_sched_out(task, next);
+       if (static_branch(&perf_sched_events))
+               __perf_event_task_sched_out(prev, next);
 }
 
 extern void perf_event_mmap(struct vm_area_struct *vma);
@@ -1139,10 +1144,11 @@ extern void perf_event_disable(struct perf_event *event);
 extern void perf_event_task_tick(void);
 #else
 static inline void
-perf_event_task_sched_in(struct task_struct *task)                     { }
+perf_event_task_sched_in(struct task_struct *prev,
+                        struct task_struct *task)                      { }
 static inline void
-perf_event_task_sched_out(struct task_struct *task,
-                           struct task_struct *next)                   { }
+perf_event_task_sched_out(struct task_struct *prev,
+                         struct task_struct *next)                     { }
 static inline int perf_event_init_task(struct task_struct *child)      { return 0; }
 static inline void perf_event_exit_task(struct task_struct *child)     { }
 static inline void perf_event_free_task(struct task_struct *task)      { }
index eec3bae..8fc7dd1 100644 (file)
@@ -22,6 +22,7 @@ extern int            __set_personality(unsigned int);
  * These occupy the top three bytes.
  */
 enum {
+       UNAME26 =               0x0020000,
        ADDR_NO_RANDOMIZE =     0x0040000,      /* disable randomization of VA space */
        FDPIC_FUNCPTRS =        0x0080000,      /* userspace function ptrs point to descriptors
                                                 * (signal handling)
index 21097cb..f9ec173 100644 (file)
@@ -72,8 +72,6 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 extern void pm_genpd_init(struct generic_pm_domain *genpd,
                          struct dev_power_governor *gov, bool is_off);
 extern int pm_genpd_poweron(struct generic_pm_domain *genpd);
-extern void pm_genpd_poweroff_unused(void);
-extern void genpd_queue_power_off_work(struct generic_pm_domain *genpd);
 #else
 static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
                                      struct device *dev)
@@ -101,8 +99,14 @@ static inline int pm_genpd_poweron(struct generic_pm_domain *genpd)
 {
        return -ENOSYS;
 }
-static inline void pm_genpd_poweroff_unused(void) {}
+#endif
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS_RUNTIME
+extern void genpd_queue_power_off_work(struct generic_pm_domain *genpd);
+extern void pm_genpd_poweroff_unused(void);
+#else
 static inline void genpd_queue_power_off_work(struct generic_pm_domain *gpd) {}
+static inline void pm_genpd_poweroff_unused(void) {}
 #endif
 
 #endif /* _LINUX_PM_DOMAIN_H */
index 5e3e25a..63d2df4 100644 (file)
@@ -14,6 +14,7 @@ struct platform_pwm_backlight_data {
        unsigned int pwm_period_ns;
        int (*init)(struct device *dev);
        int (*notify)(struct device *dev, int brightness);
+       void (*notify_after)(struct device *dev, int brightness);
        void (*exit)(struct device *dev);
        int (*check_fb)(struct device *dev, struct fb_info *info);
 };
index 26f6ea4..b47771a 100644 (file)
@@ -123,7 +123,7 @@ struct regulator_bulk_data {
        const char *supply;
        struct regulator *consumer;
 
-       /* Internal use */
+       /* private: Internal use */
        int ret;
 };
 
index 9026b30..218168a 100644 (file)
 #define  RIO_PEF_PROCESSOR             0x20000000      /* [I] Processor */
 #define  RIO_PEF_SWITCH                        0x10000000      /* [I] Switch */
 #define  RIO_PEF_MULTIPORT             0x08000000      /* [VI, 2.1] Multiport */
-#define  RIO_PEF_INB_MBOX              0x00f00000      /* [II] Mailboxes */
-#define  RIO_PEF_INB_MBOX0             0x00800000      /* [II] Mailbox 0 */
-#define  RIO_PEF_INB_MBOX1             0x00400000      /* [II] Mailbox 1 */
-#define  RIO_PEF_INB_MBOX2             0x00200000      /* [II] Mailbox 2 */
-#define  RIO_PEF_INB_MBOX3             0x00100000      /* [II] Mailbox 3 */
-#define  RIO_PEF_INB_DOORBELL          0x00080000      /* [II] Doorbells */
+#define  RIO_PEF_INB_MBOX              0x00f00000      /* [II, <= 1.2] Mailboxes */
+#define  RIO_PEF_INB_MBOX0             0x00800000      /* [II, <= 1.2] Mailbox 0 */
+#define  RIO_PEF_INB_MBOX1             0x00400000      /* [II, <= 1.2] Mailbox 1 */
+#define  RIO_PEF_INB_MBOX2             0x00200000      /* [II, <= 1.2] Mailbox 2 */
+#define  RIO_PEF_INB_MBOX3             0x00100000      /* [II, <= 1.2] Mailbox 3 */
+#define  RIO_PEF_INB_DOORBELL          0x00080000      /* [II, <= 1.2] Doorbells */
 #define  RIO_PEF_EXT_RT                        0x00000200      /* [III, 1.3] Extended route table support */
 #define  RIO_PEF_STD_RT                        0x00000100      /* [III, 1.3] Standard route table support */
 #define  RIO_PEF_CTLS                  0x00000010      /* [III] CTLS */
 #define        RIO_SWITCH_RT_LIMIT     0x34    /* [III, 1.3] Switch Route Table Destination ID Limit CAR */
 #define         RIO_RT_MAX_DESTID              0x0000ffff
 
-#define RIO_MBOX_CSR           0x40    /* [II] Mailbox CSR */
+#define RIO_MBOX_CSR           0x40    /* [II, <= 1.2] Mailbox CSR */
 #define  RIO_MBOX0_AVAIL               0x80000000      /* [II] Mbox 0 avail */
 #define  RIO_MBOX0_FULL                        0x40000000      /* [II] Mbox 0 full */
 #define  RIO_MBOX0_EMPTY               0x20000000      /* [II] Mbox 0 empty */
 #define  RIO_MBOX3_FAIL                        0x00000008      /* [II] Mbox 3 fail */
 #define  RIO_MBOX3_ERROR               0x00000004      /* [II] Mbox 3 error */
 
-#define RIO_WRITE_PORT_CSR     0x44    /* [I] Write Port CSR */
-#define RIO_DOORBELL_CSR       0x44    /* [II] Doorbell CSR */
+#define RIO_WRITE_PORT_CSR     0x44    /* [I, <= 1.2] Write Port CSR */
+#define RIO_DOORBELL_CSR       0x44    /* [II, <= 1.2] Doorbell CSR */
 #define  RIO_DOORBELL_AVAIL            0x80000000      /* [II] Doorbell avail */
 #define  RIO_DOORBELL_FULL             0x40000000      /* [II] Doorbell full */
 #define  RIO_DOORBELL_EMPTY            0x20000000      /* [II] Doorbell empty */
index b27ebea..93f4d03 100644 (file)
@@ -97,6 +97,9 @@ struct rtc_pll_info {
 #define RTC_AF 0x20    /* Alarm interrupt */
 #define RTC_UF 0x10    /* Update interrupt for 1Hz RTC */
 
+
+#define RTC_MAX_FREQ   8192
+
 #ifdef __KERNEL__
 
 #include <linux/types.h>
index 8c03b98..1ff0ec2 100644 (file)
@@ -702,9 +702,6 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args);
 asmlinkage long sys_sysinfo(struct sysinfo __user *info);
 asmlinkage long sys_sysfs(int option,
                                unsigned long arg1, unsigned long arg2);
-asmlinkage long sys_nfsservctl(int cmd,
-                               struct nfsctl_arg __user *arg,
-                               void __user *res);
 asmlinkage long sys_syslog(int type, char __user *buf, int len);
 asmlinkage long sys_uselib(const char __user *library);
 asmlinkage long sys_ni_syscall(void);
index b004e55..2ef4385 100644 (file)
@@ -410,7 +410,28 @@ struct gps_event_hdr {
        u16 plen;
 } __attribute__ ((packed));
 
-/* platform data */
+/**
+ * struct ti_st_plat_data - platform data shared between ST driver and
+ *     platform specific board file which adds the ST device.
+ * @nshutdown_gpio: Host's GPIO line to which chip's BT_EN is connected.
+ * @dev_name: The UART/TTY name to which chip is interfaced. (eg: /dev/ttyS1)
+ * @flow_cntrl: Should always be 1, since UART's CTS/RTS is used for PM
+ *     purposes.
+ * @baud_rate: The baud rate supported by the Host UART controller, this will
+ *     be shared across with the chip via a HCI VS command from User-Space Init
+ *     Mgr application.
+ * @suspend:
+ * @resume: legacy PM routines hooked to platform specific board file, so as
+ *     to take chip-host interface specific action.
+ * @chip_enable:
+ * @chip_disable: Platform/Interface specific mux mode setting, GPIO
+ *     configuring, Host side PM disabling etc.. can be done here.
+ * @chip_asleep:
+ * @chip_awake: Chip specific deep sleep states is communicated to Host
+ *     specific board-xx.c to take actions such as cut UART clocks when chip
+ *     asleep or run host faster when chip awake etc..
+ *
+ */
 struct ti_st_plat_data {
        long nshutdown_gpio;
        unsigned char dev_name[UART_DEV_NAME_LEN]; /* uart name */
@@ -418,6 +439,10 @@ struct ti_st_plat_data {
        unsigned long baud_rate;
        int (*suspend)(struct platform_device *, pm_message_t);
        int (*resume)(struct platform_device *);
+       int (*chip_enable) (struct kim_data_s *);
+       int (*chip_disable) (struct kim_data_s *);
+       int (*chip_asleep) (struct kim_data_s *);
+       int (*chip_awake) (struct kim_data_s *);
 };
 
 #endif /* TI_WILINK_ST_H */
index 44bc0c5..5f2ede8 100644 (file)
@@ -421,6 +421,8 @@ extern void tty_driver_flush_buffer(struct tty_struct *tty);
 extern void tty_throttle(struct tty_struct *tty);
 extern void tty_unthrottle(struct tty_struct *tty);
 extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
+extern void tty_driver_remove_tty(struct tty_driver *driver,
+                                 struct tty_struct *tty);
 extern void tty_shutdown(struct tty_struct *tty);
 extern void tty_free_termios(struct tty_struct *tty);
 extern int is_current_pgrp_orphaned(void);
index 9deeac8..ecdaeb9 100644 (file)
@@ -47,6 +47,9 @@
  *
  *     This routine is called synchronously when a particular tty device
  *     is closed for the last time freeing up the resources.
+ *     Note that tty_shutdown() is not called if ops->shutdown is defined.
+ *     This means one is responsible to take care of calling ops->remove (e.g.
+ *     via tty_driver_remove_tty) and releasing tty->termios.
  *
  *
  * void (*cleanup)(struct tty_struct * tty);
index f1bfa12..2b8963f 100644 (file)
  *
  *     (thresh - thresh/DIRTY_FULL_SCOPE, thresh)
  *
- * The 1/16 region above the global dirty limit will be put to maximum pauses:
- *
- *     (limit, limit + limit/DIRTY_MAXPAUSE_AREA)
- *
- * The 1/16 region above the max-pause region, dirty exceeded bdi's will be put
- * to loops:
- *
- *     (limit + limit/DIRTY_MAXPAUSE_AREA, limit + limit/DIRTY_PASSGOOD_AREA)
- *
  * Further beyond, all dirtier tasks will enter a loop waiting (possibly long
  * time) for the dirty pages to drop, unless written enough pages.
  *
@@ -31,8 +22,6 @@
  */
 #define DIRTY_SCOPE            8
 #define DIRTY_FULL_SCOPE       (DIRTY_SCOPE / 2)
-#define DIRTY_MAXPAUSE_AREA            16
-#define DIRTY_PASSGOOD_AREA            8
 
 /*
  * 4MB minimal write chunk size
index 342dcf1..a6326ef 100644 (file)
@@ -288,6 +288,35 @@ enum p9_perm_t {
        P9_DMSETVTX = 0x00010000,
 };
 
+/* 9p2000.L open flags */
+#define P9_DOTL_RDONLY        00000000
+#define P9_DOTL_WRONLY        00000001
+#define P9_DOTL_RDWR          00000002
+#define P9_DOTL_NOACCESS      00000003
+#define P9_DOTL_CREATE        00000100
+#define P9_DOTL_EXCL          00000200
+#define P9_DOTL_NOCTTY        00000400
+#define P9_DOTL_TRUNC         00001000
+#define P9_DOTL_APPEND        00002000
+#define P9_DOTL_NONBLOCK      00004000
+#define P9_DOTL_DSYNC         00010000
+#define P9_DOTL_FASYNC        00020000
+#define P9_DOTL_DIRECT        00040000
+#define P9_DOTL_LARGEFILE     00100000
+#define P9_DOTL_DIRECTORY     00200000
+#define P9_DOTL_NOFOLLOW      00400000
+#define P9_DOTL_NOATIME       01000000
+#define P9_DOTL_CLOEXEC       02000000
+#define P9_DOTL_SYNC          04000000
+
+/* 9p2000.L at flags */
+#define P9_DOTL_AT_REMOVEDIR           0x200
+
+/* 9p2000.L lock type */
+#define P9_LOCK_TYPE_RDLCK 0
+#define P9_LOCK_TYPE_WRLCK 1
+#define P9_LOCK_TYPE_UNLCK 2
+
 /**
  * enum p9_qid_t - QID types
  * @P9_QTDIR: directory
index d17f47f..401d73b 100644 (file)
@@ -1744,6 +1744,8 @@ struct wiphy_wowlan_support {
  *     by default for perm_addr. In this case, the mask should be set to
  *     all-zeroes. In this case it is assumed that the device can handle
  *     the same number of arbitrary MAC addresses.
+ * @registered: protects ->resume and ->suspend sysfs callbacks against
+ *     unregister hardware
  * @debugfsdir: debugfs directory used for this wiphy, will be renamed
  *     automatically on wiphy renames
  * @dev: (virtual) struct device for this wiphy
@@ -1865,6 +1867,9 @@ struct wiphy {
         * you need use set_wiphy_dev() (see below) */
        struct device dev;
 
+       /* protects ->resume, ->suspend sysfs callbacks against unregister hw */
+       bool registered;
+
        /* dir in debugfs: ieee80211/<wiphyname> */
        struct dentry *debugfsdir;
 
index 99e0308..ffd9bc7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Platform data for Texas Instruments TLV320AIC3x codec
  *
- * Author: Jarkko Nikula <jhnikula@gmail.com>
+ * Author: Jarkko Nikula <jarkko.nikula@bitmer.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
index 2de8fe9..126c675 100644 (file)
@@ -27,6 +27,12 @@ struct target_core_fabric_ops {
        int (*tpg_check_demo_mode_cache)(struct se_portal_group *);
        int (*tpg_check_demo_mode_write_protect)(struct se_portal_group *);
        int (*tpg_check_prod_mode_write_protect)(struct se_portal_group *);
+       /*
+        * Optionally used by fabrics to allow demo-mode login, but not
+        * expose any TPG LUNs, and return 'not connected' in standard
+        * inquiry response
+        */
+       int (*tpg_check_demo_mode_login_only)(struct se_portal_group *);
        struct se_node_acl *(*tpg_alloc_fabric_acl)(
                                        struct se_portal_group *);
        void (*tpg_release_fabric_acl)(struct se_portal_group *,
index bf36654..05c5e61 100644 (file)
@@ -8,6 +8,8 @@
 #include <linux/blkdev.h>
 #include <linux/tracepoint.h>
 
+#define RWBS_LEN       8
+
 DECLARE_EVENT_CLASS(block_rq_with_error,
 
        TP_PROTO(struct request_queue *q, struct request *rq),
@@ -19,7 +21,7 @@ DECLARE_EVENT_CLASS(block_rq_with_error,
                __field(  sector_t,     sector                  )
                __field(  unsigned int, nr_sector               )
                __field(  int,          errors                  )
-               __array(  char,         rwbs,   6               )
+               __array(  char,         rwbs,   RWBS_LEN        )
                __dynamic_array( char,  cmd,    blk_cmd_buf_len(rq)     )
        ),
 
@@ -104,7 +106,7 @@ DECLARE_EVENT_CLASS(block_rq,
                __field(  sector_t,     sector                  )
                __field(  unsigned int, nr_sector               )
                __field(  unsigned int, bytes                   )
-               __array(  char,         rwbs,   6               )
+               __array(  char,         rwbs,   RWBS_LEN        )
                __array(  char,         comm,   TASK_COMM_LEN   )
                __dynamic_array( char,  cmd,    blk_cmd_buf_len(rq)     )
        ),
@@ -183,7 +185,7 @@ TRACE_EVENT(block_bio_bounce,
                __field( dev_t,         dev                     )
                __field( sector_t,      sector                  )
                __field( unsigned int,  nr_sector               )
-               __array( char,          rwbs,   6               )
+               __array( char,          rwbs,   RWBS_LEN        )
                __array( char,          comm,   TASK_COMM_LEN   )
        ),
 
@@ -222,7 +224,7 @@ TRACE_EVENT(block_bio_complete,
                __field( sector_t,      sector          )
                __field( unsigned,      nr_sector       )
                __field( int,           error           )
-               __array( char,          rwbs,   6       )
+               __array( char,          rwbs,   RWBS_LEN)
        ),
 
        TP_fast_assign(
@@ -249,7 +251,7 @@ DECLARE_EVENT_CLASS(block_bio,
                __field( dev_t,         dev                     )
                __field( sector_t,      sector                  )
                __field( unsigned int,  nr_sector               )
-               __array( char,          rwbs,   6               )
+               __array( char,          rwbs,   RWBS_LEN        )
                __array( char,          comm,   TASK_COMM_LEN   )
        ),
 
@@ -321,7 +323,7 @@ DECLARE_EVENT_CLASS(block_get_rq,
                __field( dev_t,         dev                     )
                __field( sector_t,      sector                  )
                __field( unsigned int,  nr_sector               )
-               __array( char,          rwbs,   6               )
+               __array( char,          rwbs,   RWBS_LEN        )
                __array( char,          comm,   TASK_COMM_LEN   )
         ),
 
@@ -456,7 +458,7 @@ TRACE_EVENT(block_split,
                __field( dev_t,         dev                             )
                __field( sector_t,      sector                          )
                __field( sector_t,      new_sector                      )
-               __array( char,          rwbs,           6               )
+               __array( char,          rwbs,           RWBS_LEN        )
                __array( char,          comm,           TASK_COMM_LEN   )
        ),
 
@@ -498,7 +500,7 @@ TRACE_EVENT(block_bio_remap,
                __field( unsigned int,  nr_sector       )
                __field( dev_t,         old_dev         )
                __field( sector_t,      old_sector      )
-               __array( char,          rwbs,   6       )
+               __array( char,          rwbs,   RWBS_LEN)
        ),
 
        TP_fast_assign(
@@ -542,7 +544,7 @@ TRACE_EVENT(block_rq_remap,
                __field( unsigned int,  nr_sector       )
                __field( dev_t,         old_dev         )
                __field( sector_t,      old_sector      )
-               __array( char,          rwbs,   6       )
+               __array( char,          rwbs,   RWBS_LEN)
        ),
 
        TP_fast_assign(
index b8785e2..fbe38f2 100644 (file)
@@ -399,14 +399,54 @@ void perf_cgroup_switch(struct task_struct *task, int mode)
        local_irq_restore(flags);
 }
 
-static inline void perf_cgroup_sched_out(struct task_struct *task)
+static inline void perf_cgroup_sched_out(struct task_struct *task,
+                                        struct task_struct *next)
 {
-       perf_cgroup_switch(task, PERF_CGROUP_SWOUT);
+       struct perf_cgroup *cgrp1;
+       struct perf_cgroup *cgrp2 = NULL;
+
+       /*
+        * we come here when we know perf_cgroup_events > 0
+        */
+       cgrp1 = perf_cgroup_from_task(task);
+
+       /*
+        * next is NULL when called from perf_event_enable_on_exec()
+        * that will systematically cause a cgroup_switch()
+        */
+       if (next)
+               cgrp2 = perf_cgroup_from_task(next);
+
+       /*
+        * only schedule out current cgroup events if we know
+        * that we are switching to a different cgroup. Otherwise,
+        * do no touch the cgroup events.
+        */
+       if (cgrp1 != cgrp2)
+               perf_cgroup_switch(task, PERF_CGROUP_SWOUT);
 }
 
-static inline void perf_cgroup_sched_in(struct task_struct *task)
+static inline void perf_cgroup_sched_in(struct task_struct *prev,
+                                       struct task_struct *task)
 {
-       perf_cgroup_switch(task, PERF_CGROUP_SWIN);
+       struct perf_cgroup *cgrp1;
+       struct perf_cgroup *cgrp2 = NULL;
+
+       /*
+        * we come here when we know perf_cgroup_events > 0
+        */
+       cgrp1 = perf_cgroup_from_task(task);
+
+       /* prev can never be NULL */
+       cgrp2 = perf_cgroup_from_task(prev);
+
+       /*
+        * only need to schedule in cgroup events if we are changing
+        * cgroup during ctxsw. Cgroup events were not scheduled
+        * out of ctxsw out if that was not the case.
+        */
+       if (cgrp1 != cgrp2)
+               perf_cgroup_switch(task, PERF_CGROUP_SWIN);
 }
 
 static inline int perf_cgroup_connect(int fd, struct perf_event *event,
@@ -518,11 +558,13 @@ static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx)
 {
 }
 
-static inline void perf_cgroup_sched_out(struct task_struct *task)
+static inline void perf_cgroup_sched_out(struct task_struct *task,
+                                        struct task_struct *next)
 {
 }
 
-static inline void perf_cgroup_sched_in(struct task_struct *task)
+static inline void perf_cgroup_sched_in(struct task_struct *prev,
+                                       struct task_struct *task)
 {
 }
 
@@ -1988,7 +2030,7 @@ void __perf_event_task_sched_out(struct task_struct *task,
         * cgroup event are system-wide mode only
         */
        if (atomic_read(&__get_cpu_var(perf_cgroup_events)))
-               perf_cgroup_sched_out(task);
+               perf_cgroup_sched_out(task, next);
 }
 
 static void task_ctx_sched_out(struct perf_event_context *ctx)
@@ -2153,7 +2195,8 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx,
  * accessing the event control register. If a NMI hits, then it will
  * keep the event running.
  */
-void __perf_event_task_sched_in(struct task_struct *task)
+void __perf_event_task_sched_in(struct task_struct *prev,
+                               struct task_struct *task)
 {
        struct perf_event_context *ctx;
        int ctxn;
@@ -2171,7 +2214,7 @@ void __perf_event_task_sched_in(struct task_struct *task)
         * cgroup event are system-wide mode only
         */
        if (atomic_read(&__get_cpu_var(perf_cgroup_events)))
-               perf_cgroup_sched_in(task);
+               perf_cgroup_sched_in(prev, task);
 }
 
 static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
@@ -2427,7 +2470,7 @@ static void perf_event_enable_on_exec(struct perf_event_context *ctx)
         * ctxswin cgroup events which are already scheduled
         * in.
         */
-       perf_cgroup_sched_out(current);
+       perf_cgroup_sched_out(current, NULL);
 
        raw_spin_lock(&ctx->lock);
        task_ctx_sched_out(ctx);
@@ -3353,8 +3396,8 @@ static int perf_event_index(struct perf_event *event)
 }
 
 static void calc_timer_values(struct perf_event *event,
-                               u64 *running,
-                               u64 *enabled)
+                               u64 *enabled,
+                               u64 *running)
 {
        u64 now, ctx_time;
 
@@ -5715,6 +5758,7 @@ struct pmu *perf_init_event(struct perf_event *event)
        pmu = idr_find(&pmu_idr, event->attr.type);
        rcu_read_unlock();
        if (pmu) {
+               event->pmu = pmu;
                ret = pmu->event_init(event);
                if (ret)
                        pmu = ERR_PTR(ret);
@@ -5722,6 +5766,7 @@ struct pmu *perf_init_event(struct perf_event *event)
        }
 
        list_for_each_entry_rcu(pmu, &pmus, entry) {
+               event->pmu = pmu;
                ret = pmu->event_init(event);
                if (!ret)
                        goto unlock;
@@ -5848,8 +5893,6 @@ done:
                return ERR_PTR(err);
        }
 
-       event->pmu = pmu;
-
        if (!event->parent) {
                if (event->attach_state & PERF_ATTACH_TASK)
                        jump_label_inc(&perf_sched_events);
index 3a2cab4..e38544d 100644 (file)
@@ -246,7 +246,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
                gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
 
        for (i = gc->irq_base; msk; msk >>= 1, i++) {
-               if (!msk & 0x01)
+               if (!(msk & 0x01))
                        continue;
 
                if (flags & IRQ_GC_INIT_NESTED_LOCK)
@@ -301,7 +301,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
        raw_spin_unlock(&gc_lock);
 
        for (; msk; msk >>= 1, i++) {
-               if (!msk & 0x01)
+               if (!(msk & 0x01))
                        continue;
 
                /* Remove handler first. That will mask the irq line */
index 4c60a50..039b889 100644 (file)
@@ -70,7 +70,8 @@ static inline void desc_smp_init(struct irq_desc *desc, int node) { }
 static inline int desc_node(struct irq_desc *desc) { return 0; }
 #endif
 
-static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
+static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
+               struct module *owner)
 {
        int cpu;
 
@@ -86,6 +87,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
        desc->irq_count = 0;
        desc->irqs_unhandled = 0;
        desc->name = NULL;
+       desc->owner = owner;
        for_each_possible_cpu(cpu)
                *per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
        desc_smp_init(desc, node);
@@ -128,7 +130,7 @@ static void free_masks(struct irq_desc *desc)
 static inline void free_masks(struct irq_desc *desc) { }
 #endif
 
-static struct irq_desc *alloc_desc(int irq, int node)
+static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
 {
        struct irq_desc *desc;
        gfp_t gfp = GFP_KERNEL;
@@ -147,7 +149,7 @@ static struct irq_desc *alloc_desc(int irq, int node)
        raw_spin_lock_init(&desc->lock);
        lockdep_set_class(&desc->lock, &irq_desc_lock_class);
 
-       desc_set_defaults(irq, desc, node);
+       desc_set_defaults(irq, desc, node, owner);
 
        return desc;
 
@@ -173,13 +175,14 @@ static void free_desc(unsigned int irq)
        kfree(desc);
 }
 
-static int alloc_descs(unsigned int start, unsigned int cnt, int node)
+static int alloc_descs(unsigned int start, unsigned int cnt, int node,
+                      struct module *owner)
 {
        struct irq_desc *desc;
        int i;
 
        for (i = 0; i < cnt; i++) {
-               desc = alloc_desc(start + i, node);
+               desc = alloc_desc(start + i, node, owner);
                if (!desc)
                        goto err;
                mutex_lock(&sparse_irq_lock);
@@ -227,7 +230,7 @@ int __init early_irq_init(void)
                nr_irqs = initcnt;
 
        for (i = 0; i < initcnt; i++) {
-               desc = alloc_desc(i, node);
+               desc = alloc_desc(i, node, NULL);
                set_bit(i, allocated_irqs);
                irq_insert_desc(i, desc);
        }
@@ -261,7 +264,7 @@ int __init early_irq_init(void)
                alloc_masks(&desc[i], GFP_KERNEL, node);
                raw_spin_lock_init(&desc[i].lock);
                lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
-               desc_set_defaults(i, &desc[i], node);
+               desc_set_defaults(i, &desc[i], node, NULL);
        }
        return arch_early_irq_init();
 }
@@ -276,8 +279,16 @@ static void free_desc(unsigned int irq)
        dynamic_irq_cleanup(irq);
 }
 
-static inline int alloc_descs(unsigned int start, unsigned int cnt, int node)
+static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
+                             struct module *owner)
 {
+       u32 i;
+
+       for (i = 0; i < cnt; i++) {
+               struct irq_desc *desc = irq_to_desc(start + i);
+
+               desc->owner = owner;
+       }
        return start;
 }
 
@@ -333,11 +344,13 @@ EXPORT_SYMBOL_GPL(irq_free_descs);
  * @from:      Start the search from this irq number
  * @cnt:       Number of consecutive irqs to allocate.
  * @node:      Preferred node on which the irq descriptor should be allocated
+ * @owner:     Owning module (can be NULL)
  *
  * Returns the first irq number or error code
  */
 int __ref
-irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
+__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
+                 struct module *owner)
 {
        int start, ret;
 
@@ -366,13 +379,13 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
 
        bitmap_set(allocated_irqs, start, cnt);
        mutex_unlock(&sparse_irq_lock);
-       return alloc_descs(start, cnt, node);
+       return alloc_descs(start, cnt, node, owner);
 
 err:
        mutex_unlock(&sparse_irq_lock);
        return ret;
 }
-EXPORT_SYMBOL_GPL(irq_alloc_descs);
+EXPORT_SYMBOL_GPL(__irq_alloc_descs);
 
 /**
  * irq_reserve_irqs - mark irqs allocated
@@ -440,7 +453,7 @@ void dynamic_irq_cleanup(unsigned int irq)
        unsigned long flags;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       desc_set_defaults(irq, desc, desc_node(desc));
+       desc_set_defaults(irq, desc, desc_node(desc), NULL);
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
 
index 0a7840a..9b956fa 100644 (file)
@@ -883,6 +883,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 
        if (desc->irq_data.chip == &no_irq_chip)
                return -ENOSYS;
+       if (!try_module_get(desc->owner))
+               return -ENODEV;
        /*
         * Some drivers like serial.c use request_irq() heavily,
         * so we have to be careful not to interfere with a
@@ -906,8 +908,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
         */
        nested = irq_settings_is_nested_thread(desc);
        if (nested) {
-               if (!new->thread_fn)
-                       return -EINVAL;
+               if (!new->thread_fn) {
+                       ret = -EINVAL;
+                       goto out_mput;
+               }
                /*
                 * Replace the primary handler which was provided from
                 * the driver for non nested interrupt handling by the
@@ -929,8 +933,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 
                t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
                                   new->name);
-               if (IS_ERR(t))
-                       return PTR_ERR(t);
+               if (IS_ERR(t)) {
+                       ret = PTR_ERR(t);
+                       goto out_mput;
+               }
                /*
                 * We keep the reference to the task struct even if
                 * the thread dies to avoid that the interrupt code
@@ -1095,6 +1101,8 @@ out_thread:
                        kthread_stop(t);
                put_task_struct(t);
        }
+out_mput:
+       module_put(desc->owner);
        return ret;
 }
 
@@ -1203,6 +1211,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
                put_task_struct(action->thread);
        }
 
+       module_put(desc->owner);
        return action;
 }
 
index 8c24294..91d67ce 100644 (file)
@@ -3111,7 +3111,13 @@ static int match_held_lock(struct held_lock *hlock, struct lockdep_map *lock)
                if (!class)
                        class = look_up_lock_class(lock, 0);
 
-               if (DEBUG_LOCKS_WARN_ON(!class))
+               /*
+                * If look_up_lock_class() failed to find a class, we're trying
+                * to test if we hold a lock that has never yet been acquired.
+                * Clearly if the lock hasn't been acquired _ever_, we're not
+                * holding it either, so report failure.
+                */
+               if (!class)
                        return 0;
 
                if (DEBUG_LOCKS_WARN_ON(!hlock->nest_lock))
index b1914cb..3744c59 100644 (file)
@@ -231,3 +231,7 @@ config PM_CLK
 config PM_GENERIC_DOMAINS
        bool
        depends on PM
+
+config PM_GENERIC_DOMAINS_RUNTIME
+       def_bool y
+       depends on PM_RUNTIME && PM_GENERIC_DOMAINS
index 836a2ae..28a40d8 100644 (file)
@@ -1604,7 +1604,7 @@ static int __init printk_late_init(void)
        struct console *con;
 
        for_each_console(con) {
-               if (con->flags & CON_BOOT) {
+               if (!keep_bootcon && con->flags & CON_BOOT) {
                        printk(KERN_INFO "turn off boot console %s%d\n",
                                con->name, con->index);
                        unregister_console(con);
index ccacdbd..ec5f472 100644 (file)
@@ -3065,7 +3065,7 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
 #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
        local_irq_disable();
 #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
-       perf_event_task_sched_in(current);
+       perf_event_task_sched_in(prev, current);
 #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
        local_irq_enable();
 #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
@@ -4279,9 +4279,9 @@ pick_next_task(struct rq *rq)
 }
 
 /*
- * schedule() is the main scheduler function.
+ * __schedule() is the main scheduler function.
  */
-asmlinkage void __sched schedule(void)
+static void __sched __schedule(void)
 {
        struct task_struct *prev, *next;
        unsigned long *switch_count;
@@ -4322,16 +4322,6 @@ need_resched:
                                if (to_wakeup)
                                        try_to_wake_up_local(to_wakeup);
                        }
-
-                       /*
-                        * If we are going to sleep and we have plugged IO
-                        * queued, make sure to submit it to avoid deadlocks.
-                        */
-                       if (blk_needs_flush_plug(prev)) {
-                               raw_spin_unlock(&rq->lock);
-                               blk_schedule_flush_plug(prev);
-                               raw_spin_lock(&rq->lock);
-                       }
                }
                switch_count = &prev->nvcsw;
        }
@@ -4369,6 +4359,26 @@ need_resched:
        if (need_resched())
                goto need_resched;
 }
+
+static inline void sched_submit_work(struct task_struct *tsk)
+{
+       if (!tsk->state)
+               return;
+       /*
+        * If we are going to sleep and we have plugged IO queued,
+        * make sure to submit it to avoid deadlocks.
+        */
+       if (blk_needs_flush_plug(tsk))
+               blk_schedule_flush_plug(tsk);
+}
+
+asmlinkage void schedule(void)
+{
+       struct task_struct *tsk = current;
+
+       sched_submit_work(tsk);
+       __schedule();
+}
 EXPORT_SYMBOL(schedule);
 
 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
@@ -4435,7 +4445,7 @@ asmlinkage void __sched notrace preempt_schedule(void)
 
        do {
                add_preempt_count_notrace(PREEMPT_ACTIVE);
-               schedule();
+               __schedule();
                sub_preempt_count_notrace(PREEMPT_ACTIVE);
 
                /*
@@ -4463,7 +4473,7 @@ asmlinkage void __sched preempt_schedule_irq(void)
        do {
                add_preempt_count(PREEMPT_ACTIVE);
                local_irq_enable();
-               schedule();
+               __schedule();
                local_irq_disable();
                sub_preempt_count(PREEMPT_ACTIVE);
 
@@ -5588,7 +5598,7 @@ static inline int should_resched(void)
 static void __cond_resched(void)
 {
        add_preempt_count(PREEMPT_ACTIVE);
-       schedule();
+       __schedule();
        sub_preempt_count(PREEMPT_ACTIVE);
 }
 
@@ -7443,6 +7453,7 @@ static void __sdt_free(const struct cpumask *cpu_map)
                        struct sched_domain *sd = *per_cpu_ptr(sdd->sd, j);
                        if (sd && (sd->flags & SD_OVERLAP))
                                free_sched_groups(sd->groups, 0);
+                       kfree(*per_cpu_ptr(sdd->sd, j));
                        kfree(*per_cpu_ptr(sdd->sg, j));
                        kfree(*per_cpu_ptr(sdd->sgp, j));
                }
index dd948a1..18ee1d2 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/fs_struct.h>
 #include <linux/gfp.h>
 #include <linux/syscore_ops.h>
+#include <linux/version.h>
+#include <linux/ctype.h>
 
 #include <linux/compat.h>
 #include <linux/syscalls.h>
@@ -44,6 +46,8 @@
 #include <linux/user_namespace.h>
 
 #include <linux/kmsg_dump.h>
+/* Move somewhere else to avoid recompiling? */
+#include <generated/utsrelease.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -1161,6 +1165,34 @@ DECLARE_RWSEM(uts_sem);
 #define override_architecture(name)    0
 #endif
 
+/*
+ * Work around broken programs that cannot handle "Linux 3.0".
+ * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
+ */
+static int override_release(char __user *release, int len)
+{
+       int ret = 0;
+       char buf[len];
+
+       if (current->personality & UNAME26) {
+               char *rest = UTS_RELEASE;
+               int ndots = 0;
+               unsigned v;
+
+               while (*rest) {
+                       if (*rest == '.' && ++ndots >= 3)
+                               break;
+                       if (!isdigit(*rest) && *rest != '.')
+                               break;
+                       rest++;
+               }
+               v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
+               snprintf(buf, len, "2.6.%u%s", v, rest);
+               ret = copy_to_user(release, buf, len);
+       }
+       return ret;
+}
+
 SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
 {
        int errno = 0;
@@ -1170,6 +1202,8 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
                errno = -EFAULT;
        up_read(&uts_sem);
 
+       if (!errno && override_release(name->release, sizeof(name->release)))
+               errno = -EFAULT;
        if (!errno && override_architecture(name))
                errno = -EFAULT;
        return errno;
@@ -1191,6 +1225,8 @@ SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
                error = -EFAULT;
        up_read(&uts_sem);
 
+       if (!error && override_release(name->release, sizeof(name->release)))
+               error = -EFAULT;
        if (!error && override_architecture(name))
                error = -EFAULT;
        return error;
@@ -1225,6 +1261,8 @@ SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
 
        if (!error && override_architecture(name))
                error = -EFAULT;
+       if (!error && override_release(name->release, sizeof(name->release)))
+               error = -EFAULT;
        return error ? -EFAULT : 0;
 }
 #endif
index 62cbc88..a9a5de0 100644 (file)
@@ -16,7 +16,6 @@ asmlinkage long sys_ni_syscall(void)
        return -ENOSYS;
 }
 
-cond_syscall(sys_nfsservctl);
 cond_syscall(sys_quotactl);
 cond_syscall(sys32_quotactl);
 cond_syscall(sys_acct);
index 3b8e028..e8bffbe 100644 (file)
@@ -1,6 +1,6 @@
 #include <linux/stat.h>
 #include <linux/sysctl.h>
-#include "../fs/xfs/linux-2.6/xfs_sysctl.h"
+#include "../fs/xfs/xfs_sysctl.h"
 #include <linux/sunrpc/debug.h>
 #include <linux/string.h>
 #include <net/ip_vs.h>
index 4e4932a..362da65 100644 (file)
@@ -1,6 +1,6 @@
 #include <linux/stat.h>
 #include <linux/sysctl.h>
-#include "../fs/xfs/linux-2.6/xfs_sysctl.h"
+#include "../fs/xfs/xfs_sysctl.h"
 #include <linux/sunrpc/debug.h>
 #include <linux/string.h>
 #include <net/ip_vs.h>
index 59f369f..ea5e1a9 100644 (file)
@@ -441,6 +441,8 @@ static int alarm_timer_create(struct k_itimer *new_timer)
 static void alarm_timer_get(struct k_itimer *timr,
                                struct itimerspec *cur_setting)
 {
+       memset(cur_setting, 0, sizeof(struct itimerspec));
+
        cur_setting->it_interval =
                        ktime_to_timespec(timr->it.alarmtimer.period);
        cur_setting->it_value =
@@ -479,11 +481,17 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
        if (!rtcdev)
                return -ENOTSUPP;
 
-       /* Save old values */
-       old_setting->it_interval =
-                       ktime_to_timespec(timr->it.alarmtimer.period);
-       old_setting->it_value =
-                       ktime_to_timespec(timr->it.alarmtimer.node.expires);
+       /*
+        * XXX HACK! Currently we can DOS a system if the interval
+        * period on alarmtimers is too small. Cap the interval here
+        * to 100us and solve this properly in a future patch! -jstultz
+        */
+       if ((new_setting->it_interval.tv_sec == 0) &&
+                       (new_setting->it_interval.tv_nsec < 100000))
+               new_setting->it_interval.tv_nsec = 100000;
+
+       if (old_setting)
+               alarm_timer_get(timr, old_setting);
 
        /* If the timer was already set, cancel it */
        alarm_cancel(&timr->it.alarmtimer);
index 6957aa2..7c910a5 100644 (file)
@@ -206,6 +206,8 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
        what |= MASK_TC_BIT(rw, RAHEAD);
        what |= MASK_TC_BIT(rw, META);
        what |= MASK_TC_BIT(rw, DISCARD);
+       what |= MASK_TC_BIT(rw, FLUSH);
+       what |= MASK_TC_BIT(rw, FUA);
 
        pid = tsk->pid;
        if (act_log_check(bt, what, sector, pid))
@@ -1054,6 +1056,9 @@ static void fill_rwbs(char *rwbs, const struct blk_io_trace *t)
                goto out;
        }
 
+       if (tc & BLK_TC_FLUSH)
+               rwbs[i++] = 'F';
+
        if (tc & BLK_TC_DISCARD)
                rwbs[i++] = 'D';
        else if (tc & BLK_TC_WRITE)
@@ -1063,10 +1068,10 @@ static void fill_rwbs(char *rwbs, const struct blk_io_trace *t)
        else
                rwbs[i++] = 'N';
 
+       if (tc & BLK_TC_FUA)
+               rwbs[i++] = 'F';
        if (tc & BLK_TC_AHEAD)
                rwbs[i++] = 'A';
-       if (tc & BLK_TC_BARRIER)
-               rwbs[i++] = 'B';
        if (tc & BLK_TC_SYNC)
                rwbs[i++] = 'S';
        if (tc & BLK_TC_META)
@@ -1132,7 +1137,7 @@ typedef int (blk_log_action_t) (struct trace_iterator *iter, const char *act);
 
 static int blk_log_action_classic(struct trace_iterator *iter, const char *act)
 {
-       char rwbs[6];
+       char rwbs[RWBS_LEN];
        unsigned long long ts  = iter->ts;
        unsigned long nsec_rem = do_div(ts, NSEC_PER_SEC);
        unsigned secs          = (unsigned long)ts;
@@ -1148,7 +1153,7 @@ static int blk_log_action_classic(struct trace_iterator *iter, const char *act)
 
 static int blk_log_action(struct trace_iterator *iter, const char *act)
 {
-       char rwbs[6];
+       char rwbs[RWBS_LEN];
        const struct blk_io_trace *t = te_blk_io_trace(iter->ent);
 
        fill_rwbs(rwbs, t);
@@ -1561,7 +1566,7 @@ static const struct {
 } mask_maps[] = {
        { BLK_TC_READ,          "read"          },
        { BLK_TC_WRITE,         "write"         },
-       { BLK_TC_BARRIER,       "barrier"       },
+       { BLK_TC_FLUSH,         "flush"         },
        { BLK_TC_SYNC,          "sync"          },
        { BLK_TC_QUEUE,         "queue"         },
        { BLK_TC_REQUEUE,       "requeue"       },
@@ -1573,6 +1578,7 @@ static const struct {
        { BLK_TC_META,          "meta"          },
        { BLK_TC_DISCARD,       "discard"       },
        { BLK_TC_DRV_DATA,      "drv_data"      },
+       { BLK_TC_FUA,           "fua"           },
 };
 
 static int blk_trace_str2mask(const char *str)
@@ -1788,6 +1794,9 @@ void blk_fill_rwbs(char *rwbs, u32 rw, int bytes)
 {
        int i = 0;
 
+       if (rw & REQ_FLUSH)
+               rwbs[i++] = 'F';
+
        if (rw & WRITE)
                rwbs[i++] = 'W';
        else if (rw & REQ_DISCARD)
@@ -1797,6 +1806,8 @@ void blk_fill_rwbs(char *rwbs, u32 rw, int bytes)
        else
                rwbs[i++] = 'N';
 
+       if (rw & REQ_FUA)
+               rwbs[i++] = 'F';
        if (rw & REQ_RAHEAD)
                rwbs[i++] = 'A';
        if (rw & REQ_SYNC)
index d5d175c..3f5bc6d 100644 (file)
@@ -12,7 +12,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
         idr.o int_sqrt.o extable.o prio_tree.o \
         sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
         proportions.o prio_heap.o ratelimit.o show_mem.o \
-        is_single_threaded.o plist.o decompress.o find_next_bit.o
+        is_single_threaded.o plist.o decompress.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
@@ -22,7 +22,7 @@ lib-y += kobject.o kref.o klist.o
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
         bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
         string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o \
-        bsearch.o find_last_bit.o
+        bsearch.o find_last_bit.o find_next_bit.o
 obj-y += kstrtox.o
 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 
index 693394d..5ef672c 100644 (file)
@@ -326,7 +326,7 @@ static struct page_address_slot {
        spinlock_t lock;                        /* Protect this bucket's list */
 } ____cacheline_aligned_in_smp page_address_htable[1<<PA_HASH_ORDER];
 
-static struct page_address_slot *page_slot(struct page *page)
+static struct page_address_slot *page_slot(const struct page *page)
 {
        return &page_address_htable[hash_ptr(page, PA_HASH_ORDER)];
 }
@@ -337,7 +337,7 @@ static struct page_address_slot *page_slot(struct page *page)
  *
  * Returns the page's virtual address.
  */
-void *page_address(struct page *page)
+void *page_address(const struct page *page)
 {
        unsigned long flags;
        void *ret;
index 930de94..ebd1e86 100644 (file)
@@ -1841,29 +1841,23 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
  */
 static bool mem_cgroup_oom_lock(struct mem_cgroup *mem)
 {
-       int lock_count = -1;
        struct mem_cgroup *iter, *failed = NULL;
        bool cond = true;
 
        for_each_mem_cgroup_tree_cond(iter, mem, cond) {
-               bool locked = iter->oom_lock;
-
-               iter->oom_lock = true;
-               if (lock_count == -1)
-                       lock_count = iter->oom_lock;
-               else if (lock_count != locked) {
+               if (iter->oom_lock) {
                        /*
                         * this subtree of our hierarchy is already locked
                         * so we cannot give a lock.
                         */
-                       lock_count = 0;
                        failed = iter;
                        cond = false;
-               }
+               } else
+                       iter->oom_lock = true;
        }
 
        if (!failed)
-               goto done;
+               return true;
 
        /*
         * OK, we failed to lock the whole subtree so we have to clean up
@@ -1877,8 +1871,7 @@ static bool mem_cgroup_oom_lock(struct mem_cgroup *mem)
                }
                iter->oom_lock = false;
        }
-done:
-       return lock_count;
+       return false;
 }
 
 /*
@@ -2169,13 +2162,7 @@ static void drain_all_stock(struct mem_cgroup *root_mem, bool sync)
 
        /* Notify other cpus that system-wide "drain" is running */
        get_online_cpus();
-       /*
-        * Get a hint for avoiding draining charges on the current cpu,
-        * which must be exhausted by our charging.  It is not required that
-        * this be a precise check, so we use raw_smp_processor_id() instead of
-        * getcpu()/putcpu().
-        */
-       curcpu = raw_smp_processor_id();
+       curcpu = get_cpu();
        for_each_online_cpu(cpu) {
                struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
                struct mem_cgroup *mem;
@@ -2192,6 +2179,7 @@ static void drain_all_stock(struct mem_cgroup *root_mem, bool sync)
                                schedule_work_on(cpu, &stock->work);
                }
        }
+       put_cpu();
 
        if (!sync)
                goto out;
index d196074..0e309cd 100644 (file)
@@ -754,21 +754,10 @@ static void balance_dirty_pages(struct address_space *mapping,
                 * 200ms is typically more than enough to curb heavy dirtiers;
                 * (b) the pause time limit makes the dirtiers more responsive.
                 */
-               if (nr_dirty < dirty_thresh +
-                              dirty_thresh / DIRTY_MAXPAUSE_AREA &&
+               if (nr_dirty < dirty_thresh &&
+                   bdi_dirty < (task_bdi_thresh + bdi_thresh) / 2 &&
                    time_after(jiffies, start_time + MAX_PAUSE))
                        break;
-               /*
-                * pass-good area. When some bdi gets blocked (eg. NFS server
-                * not responding), or write bandwidth dropped dramatically due
-                * to concurrent reads, or dirty threshold suddenly dropped and
-                * the dirty pages cannot be brought down anytime soon (eg. on
-                * slow USB stick), at least let go of the good bdi's.
-                */
-               if (nr_dirty < dirty_thresh +
-                              dirty_thresh / DIRTY_PASSGOOD_AREA &&
-                   bdi_dirty < bdi_thresh)
-                       break;
 
                /*
                 * Increase the delay for each loop, up to our previous
index 464621d..7ef0903 100644 (file)
@@ -725,9 +725,10 @@ static void free_unmap_vmap_area_addr(unsigned long addr)
 #define VMAP_BBMAP_BITS_MIN    (VMAP_MAX_ALLOC*2)
 #define VMAP_MIN(x, y)         ((x) < (y) ? (x) : (y)) /* can't use min() */
 #define VMAP_MAX(x, y)         ((x) > (y) ? (x) : (y)) /* can't use max() */
-#define VMAP_BBMAP_BITS                VMAP_MIN(VMAP_BBMAP_BITS_MAX,           \
-                                       VMAP_MAX(VMAP_BBMAP_BITS_MIN,   \
-                                               VMALLOC_PAGES / NR_CPUS / 16))
+#define VMAP_BBMAP_BITS                \
+               VMAP_MIN(VMAP_BBMAP_BITS_MAX,   \
+               VMAP_MAX(VMAP_BBMAP_BITS_MIN,   \
+                       VMALLOC_PAGES / roundup_pow_of_two(NR_CPUS) / 16))
 
 #define VMAP_BLOCK_SIZE                (VMAP_BBMAP_BITS * PAGE_SIZE)
 
index 7ef6912..b7719ec 100644 (file)
@@ -2283,7 +2283,7 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
                .mem_cgroup = mem,
                .memcg_record = rec,
        };
-       unsigned long start, end;
+       ktime_t start, end;
 
        sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
                        (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
@@ -2292,7 +2292,7 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
                                                      sc.may_writepage,
                                                      sc.gfp_mask);
 
-       start = sched_clock();
+       start = ktime_get();
        /*
         * NOTE: Although we can get the priority field, using it
         * here is not a good idea, since it limits the pages we can scan.
@@ -2301,10 +2301,10 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
         * the priority and make it zero.
         */
        shrink_zone(0, zone, &sc);
-       end = sched_clock();
+       end = ktime_get();
 
        if (rec)
-               rec->elapsed += end - start;
+               rec->elapsed += ktime_to_ns(ktime_sub(end, start));
        *scanned = sc.nr_scanned;
 
        trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed);
@@ -2319,7 +2319,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
 {
        struct zonelist *zonelist;
        unsigned long nr_reclaimed;
-       unsigned long start, end;
+       ktime_t start, end;
        int nid;
        struct scan_control sc = {
                .may_writepage = !laptop_mode,
@@ -2337,7 +2337,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
                .gfp_mask = sc.gfp_mask,
        };
 
-       start = sched_clock();
+       start = ktime_get();
        /*
         * Unlike direct reclaim via alloc_pages(), memcg's reclaim doesn't
         * take care of from where we get pages. So the node where we start the
@@ -2352,9 +2352,9 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
                                            sc.gfp_mask);
 
        nr_reclaimed = do_try_to_free_pages(zonelist, &sc, &shrink);
-       end = sched_clock();
+       end = ktime_get();
        if (rec)
-               rec->elapsed += end - start;
+               rec->elapsed += ktime_to_ns(ktime_sub(end, start));
 
        trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed);
 
@@ -2529,6 +2529,9 @@ loop_again:
                                        high_wmark_pages(zone), 0, 0)) {
                                end_zone = i;
                                break;
+                       } else {
+                               /* If balanced, clear the congested flag */
+                               zone_clear_flag(zone, ZONE_CONGESTED);
                        }
                }
                if (i < 0)
index 5f27f8e..f1f2f7b 100644 (file)
@@ -167,6 +167,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb)
        if (unlikely(!skb))
                goto err_free;
 
+       skb_reset_network_header(skb);
+       skb_reset_transport_header(skb);
        return skb;
 
 err_free:
index 175b513..e317583 100644 (file)
@@ -263,7 +263,6 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
 {
        int in, out, inp, outp;
        struct virtio_chan *chan = client->trans;
-       char *rdata = (char *)req->rc+sizeof(struct p9_fcall);
        unsigned long flags;
        size_t pdata_off = 0;
        struct trans_rpage_info *rpinfo = NULL;
@@ -346,7 +345,8 @@ req_retry_pinned:
                 * Arrange in such a way that server places header in the
                 * alloced memory and payload onto the user buffer.
                 */
-               inp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata, 11);
+               inp = pack_sg_list(chan->sg, out,
+                                  VIRTQUEUE_NUM, req->rc->sdata, 11);
                /*
                 * Running executables in the filesystem may result in
                 * a read request with kernel buffer as opposed to user buffer.
@@ -366,8 +366,8 @@ req_retry_pinned:
                }
                in += inp;
        } else {
-               in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata,
-                               req->rc->capacity);
+               in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM,
+                                 req->rc->sdata, req->rc->capacity);
        }
 
        err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
@@ -592,7 +592,14 @@ static struct p9_trans_module p9_virtio_trans = {
        .close = p9_virtio_close,
        .request = p9_virtio_request,
        .cancel = p9_virtio_cancel,
-       .maxsize = PAGE_SIZE*VIRTQUEUE_NUM,
+
+       /*
+        * We leave one entry for input and one entry for response
+        * headers. We also skip one more entry to accomodate, address
+        * that are not at page boundary, that can result in an extra
+        * page in zero copy.
+        */
+       .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3),
        .pref = P9_TRANS_PREF_PAYLOAD_SEP,
        .def = 0,
        .owner = THIS_MODULE,
index 52cfd0c..d07223c 100644 (file)
@@ -558,12 +558,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
        spin_unlock_irqrestore(&rq->lock, flags);
 
        skb_queue_walk_safe(&queue, skb, tmp) {
-               struct net_device *dev = skb->dev;
+               struct net_device *dev;
+
+               br2684_push(atmvcc, skb);
+               dev = skb->dev;
 
                dev->stats.rx_bytes -= skb->len;
                dev->stats.rx_packets--;
-
-               br2684_push(atmvcc, skb);
        }
 
        /* initialize netdev carrier state */
index 8add9b4..117e0d1 100644 (file)
@@ -494,9 +494,8 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
        BT_DBG("sk %p", sk);
 
        add_wait_queue(sk_sleep(sk), &wait);
+       set_current_state(TASK_INTERRUPTIBLE);
        while (sk->sk_state != state) {
-               set_current_state(TASK_INTERRUPTIBLE);
-
                if (!timeo) {
                        err = -EINPROGRESS;
                        break;
@@ -510,12 +509,13 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
                release_sock(sk);
                timeo = schedule_timeout(timeo);
                lock_sock(sk);
+               set_current_state(TASK_INTERRUPTIBLE);
 
                err = sock_error(sk);
                if (err)
                        break;
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
        return err;
 }
index 8e6c061..e7ee531 100644 (file)
@@ -155,6 +155,7 @@ struct bnep_session {
        unsigned int  role;
        unsigned long state;
        unsigned long flags;
+       atomic_t      terminate;
        struct task_struct *task;
 
        struct ethhdr eh;
index ca39fcf..d9edfe8 100644 (file)
@@ -484,9 +484,11 @@ static int bnep_session(void *arg)
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(sk_sleep(sk), &wait);
-       while (!kthread_should_stop()) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
 
+               if (atomic_read(&s->terminate))
+                       break;
                /* RX */
                while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
                        skb_orphan(skb);
@@ -504,7 +506,7 @@ static int bnep_session(void *arg)
 
                schedule();
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        /* Cleanup session */
@@ -640,9 +642,10 @@ int bnep_del_connection(struct bnep_conndel_req *req)
        down_read(&bnep_session_sem);
 
        s = __bnep_get_session(req->dst);
-       if (s)
-               kthread_stop(s->task);
-       else
+       if (s) {
+               atomic_inc(&s->terminate);
+               wake_up_process(s->task);
+       } else
                err = -ENOENT;
 
        up_read(&bnep_session_sem);
index 040f67b..50f0d13 100644 (file)
@@ -386,7 +386,8 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl)
 
        capi_ctr_down(ctrl);
 
-       kthread_stop(session->task);
+       atomic_inc(&session->terminate);
+       wake_up_process(session->task);
 }
 
 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
index db43b54..c32638d 100644 (file)
@@ -81,6 +81,7 @@ struct cmtp_session {
 
        char name[BTNAMSIZ];
 
+       atomic_t terminate;
        struct task_struct *task;
 
        wait_queue_head_t wait;
index c5b11af..521baa4 100644 (file)
@@ -292,9 +292,11 @@ static int cmtp_session(void *arg)
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(sk_sleep(sk), &wait);
-       while (!kthread_should_stop()) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
 
+               if (atomic_read(&session->terminate))
+                       break;
                if (sk->sk_state != BT_CONNECTED)
                        break;
 
@@ -307,7 +309,7 @@ static int cmtp_session(void *arg)
 
                schedule();
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        down_write(&cmtp_session_sem);
@@ -380,16 +382,17 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
 
        if (!(session->flags & (1 << CMTP_LOOPBACK))) {
                err = cmtp_attach_device(session);
-               if (err < 0)
-                       goto detach;
+               if (err < 0) {
+                       atomic_inc(&session->terminate);
+                       wake_up_process(session->task);
+                       up_write(&cmtp_session_sem);
+                       return err;
+               }
        }
 
        up_write(&cmtp_session_sem);
        return 0;
 
-detach:
-       cmtp_detach_device(session);
-
 unlink:
        __cmtp_unlink_session(session);
 
@@ -414,7 +417,8 @@ int cmtp_del_connection(struct cmtp_conndel_req *req)
                skb_queue_purge(&session->transmit);
 
                /* Stop session thread */
-               kthread_stop(session->task);
+               atomic_inc(&session->terminate);
+               wake_up_process(session->task);
        } else
                err = -ENOENT;
 
index ec0bc3f..56943ad 100644 (file)
@@ -1209,7 +1209,6 @@ static void hci_cmd_timer(unsigned long arg)
 
        BT_ERR("%s command tx timeout", hdev->name);
        atomic_set(&hdev->cmd_cnt, 1);
-       clear_bit(HCI_RESET, &hdev->flags);
        tasklet_schedule(&hdev->cmd_task);
 }
 
@@ -1327,7 +1326,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
 
        entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
        if (!entry) {
-               return -ENOMEM;
+               err = -ENOMEM;
                goto err;
        }
 
@@ -2408,7 +2407,10 @@ static void hci_cmd_task(unsigned long arg)
                if (hdev->sent_cmd) {
                        atomic_dec(&hdev->cmd_cnt);
                        hci_send_frame(skb);
-                       mod_timer(&hdev->cmd_timer,
+                       if (test_bit(HCI_RESET, &hdev->flags))
+                               del_timer(&hdev->cmd_timer);
+                       else
+                               mod_timer(&hdev->cmd_timer,
                                  jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
                } else {
                        skb_queue_head(&hdev->cmd_q, skb);
index 43b4c2d..fb68f34 100644 (file)
@@ -764,6 +764,7 @@ static int hidp_session(void *arg)
 
        up_write(&hidp_session_sem);
 
+       kfree(session->rd_data);
        kfree(session);
        return 0;
 }
@@ -841,7 +842,8 @@ static int hidp_setup_input(struct hidp_session *session,
 
        err = input_register_device(input);
        if (err < 0) {
-               hci_conn_put_device(session->conn);
+               input_free_device(input);
+               session->input = NULL;
                return err;
        }
 
@@ -1044,8 +1046,12 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
        }
 
        err = hid_add_device(session->hid);
-       if (err < 0)
-               goto err_add_device;
+       if (err < 0) {
+               atomic_inc(&session->terminate);
+               wake_up_process(session->task);
+               up_write(&hidp_session_sem);
+               return err;
+       }
 
        if (session->input) {
                hidp_send_ctrl_message(session,
@@ -1059,12 +1065,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
        up_write(&hidp_session_sem);
        return 0;
 
-err_add_device:
-       hid_destroy_device(session->hid);
-       session->hid = NULL;
-       atomic_inc(&session->terminate);
-       wake_up_process(session->task);
-
 unlink:
        hidp_del_timer(session);
 
@@ -1090,7 +1090,6 @@ purge:
 failed:
        up_write(&hidp_session_sem);
 
-       input_free_device(session->input);
        kfree(session);
        return err;
 }
index 3204ba8..b3bdb48 100644 (file)
@@ -1159,9 +1159,8 @@ int __l2cap_wait_ack(struct sock *sk)
        int timeo = HZ/5;
 
        add_wait_queue(sk_sleep(sk), &wait);
-       while ((chan->unacked_frames > 0 && chan->conn)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-
+       set_current_state(TASK_INTERRUPTIBLE);
+       while (chan->unacked_frames > 0 && chan->conn) {
                if (!timeo)
                        timeo = HZ/5;
 
@@ -1173,6 +1172,7 @@ int __l2cap_wait_ack(struct sock *sk)
                release_sock(sk);
                timeo = schedule_timeout(timeo);
                lock_sock(sk);
+               set_current_state(TASK_INTERRUPTIBLE);
 
                err = sock_error(sk);
                if (err)
index 5c36b3e..61f1f62 100644 (file)
@@ -235,30 +235,26 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
 
        lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
-       if (sk->sk_state != BT_LISTEN) {
-               err = -EBADFD;
-               goto done;
-       }
-
        timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
        BT_DBG("sk %p timeo %ld", sk, timeo);
 
        /* Wait for an incoming connection. (wake-one). */
        add_wait_queue_exclusive(sk_sleep(sk), &wait);
-       while (!(nsk = bt_accept_dequeue(sk, newsock))) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!timeo) {
-                       err = -EAGAIN;
+
+               if (sk->sk_state != BT_LISTEN) {
+                       err = -EBADFD;
                        break;
                }
 
-               release_sock(sk);
-               timeo = schedule_timeout(timeo);
-               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+               nsk = bt_accept_dequeue(sk, newsock);
+               if (nsk)
+                       break;
 
-               if (sk->sk_state != BT_LISTEN) {
-                       err = -EBADFD;
+               if (!timeo) {
+                       err = -EAGAIN;
                        break;
                }
 
@@ -266,8 +262,12 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
                        err = sock_intr_errno(timeo);
                        break;
                }
+
+               release_sock(sk);
+               timeo = schedule_timeout(timeo);
+               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        if (err)
@@ -993,7 +993,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p
        INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
 
        sk->sk_destruct = l2cap_sock_destruct;
-       sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
+       sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
 
        sock_reset_flag(sk, SOCK_ZAPPED);
 
index 5759bb7..5ba3f6d 100644 (file)
@@ -62,7 +62,6 @@ static DEFINE_MUTEX(rfcomm_mutex);
 #define rfcomm_lock()  mutex_lock(&rfcomm_mutex)
 #define rfcomm_unlock()        mutex_unlock(&rfcomm_mutex)
 
-static unsigned long rfcomm_event;
 
 static LIST_HEAD(session_list);
 
@@ -120,7 +119,6 @@ static inline void rfcomm_schedule(void)
 {
        if (!rfcomm_thread)
                return;
-       set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
        wake_up_process(rfcomm_thread);
 }
 
@@ -2038,19 +2036,18 @@ static int rfcomm_run(void *unused)
 
        rfcomm_add_listener(BDADDR_ANY);
 
-       while (!kthread_should_stop()) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
-                       /* No pending events. Let's sleep.
-                        * Incoming connections and data will wake us up. */
-                       schedule();
-               }
-               set_current_state(TASK_RUNNING);
+
+               if (kthread_should_stop())
+                       break;
 
                /* Process stuff */
-               clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
                rfcomm_process_sessions();
+
+               schedule();
        }
+       __set_current_state(TASK_RUNNING);
 
        rfcomm_kill_listener();
 
index 8f01e6b..482722b 100644 (file)
@@ -485,11 +485,6 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
 
        lock_sock(sk);
 
-       if (sk->sk_state != BT_LISTEN) {
-               err = -EBADFD;
-               goto done;
-       }
-
        if (sk->sk_type != SOCK_STREAM) {
                err = -EINVAL;
                goto done;
@@ -501,19 +496,20 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
 
        /* Wait for an incoming connection. (wake-one). */
        add_wait_queue_exclusive(sk_sleep(sk), &wait);
-       while (!(nsk = bt_accept_dequeue(sk, newsock))) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!timeo) {
-                       err = -EAGAIN;
+
+               if (sk->sk_state != BT_LISTEN) {
+                       err = -EBADFD;
                        break;
                }
 
-               release_sock(sk);
-               timeo = schedule_timeout(timeo);
-               lock_sock(sk);
+               nsk = bt_accept_dequeue(sk, newsock);
+               if (nsk)
+                       break;
 
-               if (sk->sk_state != BT_LISTEN) {
-                       err = -EBADFD;
+               if (!timeo) {
+                       err = -EAGAIN;
                        break;
                }
 
@@ -521,8 +517,12 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
                        err = sock_intr_errno(timeo);
                        break;
                }
+
+               release_sock(sk);
+               timeo = schedule_timeout(timeo);
+               lock_sock(sk);
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        if (err)
index 4c3621b..8270f05 100644 (file)
@@ -564,30 +564,26 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag
 
        lock_sock(sk);
 
-       if (sk->sk_state != BT_LISTEN) {
-               err = -EBADFD;
-               goto done;
-       }
-
        timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
        BT_DBG("sk %p timeo %ld", sk, timeo);
 
        /* Wait for an incoming connection. (wake-one). */
        add_wait_queue_exclusive(sk_sleep(sk), &wait);
-       while (!(ch = bt_accept_dequeue(sk, newsock))) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!timeo) {
-                       err = -EAGAIN;
+
+               if (sk->sk_state != BT_LISTEN) {
+                       err = -EBADFD;
                        break;
                }
 
-               release_sock(sk);
-               timeo = schedule_timeout(timeo);
-               lock_sock(sk);
+               ch = bt_accept_dequeue(sk, newsock);
+               if (ch)
+                       break;
 
-               if (sk->sk_state != BT_LISTEN) {
-                       err = -EBADFD;
+               if (!timeo) {
+                       err = -EAGAIN;
                        break;
                }
 
@@ -595,8 +591,12 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag
                        err = sock_intr_errno(timeo);
                        break;
                }
+
+               release_sock(sk);
+               timeo = schedule_timeout(timeo);
+               lock_sock(sk);
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        if (err)
index 2cdf007..e738154 100644 (file)
@@ -231,6 +231,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
 int br_add_bridge(struct net *net, const char *name)
 {
        struct net_device *dev;
+       int res;
 
        dev = alloc_netdev(sizeof(struct net_bridge), name,
                           br_dev_setup);
@@ -240,7 +241,10 @@ int br_add_bridge(struct net *net, const char *name)
 
        dev_net_set(dev, net);
 
-       return register_netdev(dev);
+       res = register_netdev(dev);
+       if (res)
+               free_netdev(dev);
+       return res;
 }
 
 int br_del_bridge(struct net *net, const char *name)
index 2d85ca7..995cbe0 100644 (file)
@@ -1456,7 +1456,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
 {
        struct sk_buff *skb2;
        const struct ipv6hdr *ip6h;
-       struct icmp6hdr *icmp6h;
+       u8 icmp6_type;
        u8 nexthdr;
        unsigned len;
        int offset;
@@ -1502,9 +1502,9 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
        __skb_pull(skb2, offset);
        skb_reset_transport_header(skb2);
 
-       icmp6h = icmp6_hdr(skb2);
+       icmp6_type = icmp6_hdr(skb2)->icmp6_type;
 
-       switch (icmp6h->icmp6_type) {
+       switch (icmp6_type) {
        case ICMPV6_MGM_QUERY:
        case ICMPV6_MGM_REPORT:
        case ICMPV6_MGM_REDUCTION:
@@ -1520,16 +1520,23 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
                err = pskb_trim_rcsum(skb2, len);
                if (err)
                        goto out;
+               err = -EINVAL;
        }
 
+       ip6h = ipv6_hdr(skb2);
+
        switch (skb2->ip_summed) {
        case CHECKSUM_COMPLETE:
-               if (!csum_fold(skb2->csum))
+               if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb2->len,
+                                       IPPROTO_ICMPV6, skb2->csum))
                        break;
                /*FALLTHROUGH*/
        case CHECKSUM_NONE:
-               skb2->csum = 0;
-               if (skb_checksum_complete(skb2))
+               skb2->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr,
+                                                       &ip6h->daddr,
+                                                       skb2->len,
+                                                       IPPROTO_ICMPV6, 0));
+               if (__skb_checksum_complete(skb2))
                        goto out;
        }
 
@@ -1537,7 +1544,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
 
        BR_INPUT_SKB_CB(skb)->igmp = 1;
 
-       switch (icmp6h->icmp6_type) {
+       switch (icmp6_type) {
        case ICMPV6_MGM_REPORT:
            {
                struct mld_msg *mld;
index d5f2d97..1f4cb30 100644 (file)
@@ -7,27 +7,37 @@
 
 #include <linux/ceph/msgpool.h>
 
-static void *alloc_fn(gfp_t gfp_mask, void *arg)
+static void *msgpool_alloc(gfp_t gfp_mask, void *arg)
 {
        struct ceph_msgpool *pool = arg;
-       void *p;
+       struct ceph_msg *msg;
 
-       p = ceph_msg_new(0, pool->front_len, gfp_mask);
-       if (!p)
-               pr_err("msgpool %s alloc failed\n", pool->name);
-       return p;
+       msg = ceph_msg_new(0, pool->front_len, gfp_mask);
+       if (!msg) {
+               dout("msgpool_alloc %s failed\n", pool->name);
+       } else {
+               dout("msgpool_alloc %s %p\n", pool->name, msg);
+               msg->pool = pool;
+       }
+       return msg;
 }
 
-static void free_fn(void *element, void *arg)
+static void msgpool_free(void *element, void *arg)
 {
-       ceph_msg_put(element);
+       struct ceph_msgpool *pool = arg;
+       struct ceph_msg *msg = element;
+
+       dout("msgpool_release %s %p\n", pool->name, msg);
+       msg->pool = NULL;
+       ceph_msg_put(msg);
 }
 
 int ceph_msgpool_init(struct ceph_msgpool *pool,
                      int front_len, int size, bool blocking, const char *name)
 {
+       dout("msgpool %s init\n", name);
        pool->front_len = front_len;
-       pool->pool = mempool_create(size, alloc_fn, free_fn, pool);
+       pool->pool = mempool_create(size, msgpool_alloc, msgpool_free, pool);
        if (!pool->pool)
                return -ENOMEM;
        pool->name = name;
@@ -36,14 +46,17 @@ int ceph_msgpool_init(struct ceph_msgpool *pool,
 
 void ceph_msgpool_destroy(struct ceph_msgpool *pool)
 {
+       dout("msgpool %s destroy\n", pool->name);
        mempool_destroy(pool->pool);
 }
 
 struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool,
                                  int front_len)
 {
+       struct ceph_msg *msg;
+
        if (front_len > pool->front_len) {
-               pr_err("msgpool_get pool %s need front %d, pool size is %d\n",
+               dout("msgpool_get %s need front %d, pool size is %d\n",
                       pool->name, front_len, pool->front_len);
                WARN_ON(1);
 
@@ -51,14 +64,19 @@ struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool,
                return ceph_msg_new(0, front_len, GFP_NOFS);
        }
 
-       return mempool_alloc(pool->pool, GFP_NOFS);
+       msg = mempool_alloc(pool->pool, GFP_NOFS);
+       dout("msgpool_get %s %p\n", pool->name, msg);
+       return msg;
 }
 
 void ceph_msgpool_put(struct ceph_msgpool *pool, struct ceph_msg *msg)
 {
+       dout("msgpool_put %s %p\n", pool->name, msg);
+
        /* reset msg front_len; user may have changed it */
        msg->front.iov_len = pool->front_len;
        msg->hdr.front_len = cpu_to_le32(pool->front_len);
 
        kref_init(&msg->kref);  /* retake single ref */
+       mempool_free(msg, pool->pool);
 }
index ce310ee..16836a7 100644 (file)
@@ -685,6 +685,18 @@ static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
        put_osd(osd);
 }
 
+static void remove_all_osds(struct ceph_osd_client *osdc)
+{
+       dout("__remove_old_osds %p\n", osdc);
+       mutex_lock(&osdc->request_mutex);
+       while (!RB_EMPTY_ROOT(&osdc->osds)) {
+               struct ceph_osd *osd = rb_entry(rb_first(&osdc->osds),
+                                               struct ceph_osd, o_node);
+               __remove_osd(osdc, osd);
+       }
+       mutex_unlock(&osdc->request_mutex);
+}
+
 static void __move_osd_to_lru(struct ceph_osd_client *osdc,
                              struct ceph_osd *osd)
 {
@@ -701,14 +713,14 @@ static void __remove_osd_from_lru(struct ceph_osd *osd)
                list_del_init(&osd->o_osd_lru);
 }
 
-static void remove_old_osds(struct ceph_osd_client *osdc, int remove_all)
+static void remove_old_osds(struct ceph_osd_client *osdc)
 {
        struct ceph_osd *osd, *nosd;
 
        dout("__remove_old_osds %p\n", osdc);
        mutex_lock(&osdc->request_mutex);
        list_for_each_entry_safe(osd, nosd, &osdc->osd_lru, o_osd_lru) {
-               if (!remove_all && time_before(jiffies, osd->lru_ttl))
+               if (time_before(jiffies, osd->lru_ttl))
                        break;
                __remove_osd(osdc, osd);
        }
@@ -751,6 +763,7 @@ static void __insert_osd(struct ceph_osd_client *osdc, struct ceph_osd *new)
        struct rb_node *parent = NULL;
        struct ceph_osd *osd = NULL;
 
+       dout("__insert_osd %p osd%d\n", new, new->o_osd);
        while (*p) {
                parent = *p;
                osd = rb_entry(parent, struct ceph_osd, o_node);
@@ -1144,7 +1157,7 @@ static void handle_osds_timeout(struct work_struct *work)
 
        dout("osds timeout\n");
        down_read(&osdc->map_sem);
-       remove_old_osds(osdc, 0);
+       remove_old_osds(osdc);
        up_read(&osdc->map_sem);
 
        schedule_delayed_work(&osdc->osds_timeout_work,
@@ -1862,8 +1875,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc)
                ceph_osdmap_destroy(osdc->osdmap);
                osdc->osdmap = NULL;
        }
-       remove_old_osds(osdc, 1);
-       WARN_ON(!RB_EMPTY_ROOT(&osdc->osds));
+       remove_all_osds(osdc);
        mempool_destroy(osdc->req_mempool);
        ceph_msgpool_destroy(&osdc->msgpool_op);
        ceph_msgpool_destroy(&osdc->msgpool_op_reply);
index 8fab9b0..1334d7e 100644 (file)
@@ -1319,11 +1319,15 @@ static void neigh_proxy_process(unsigned long arg)
 
                if (tdif <= 0) {
                        struct net_device *dev = skb->dev;
+
                        __skb_unlink(skb, &tbl->proxy_queue);
-                       if (tbl->proxy_redo && netif_running(dev))
+                       if (tbl->proxy_redo && netif_running(dev)) {
+                               rcu_read_lock();
                                tbl->proxy_redo(skb);
-                       else
+                               rcu_read_unlock();
+                       } else {
                                kfree_skb(skb);
+                       }
 
                        dev_put(dev);
                } else if (!sched_next || tdif < sched_next)
index adf84dd..5262251 100644 (file)
@@ -558,13 +558,14 @@ int __netpoll_rx(struct sk_buff *skb)
        if (skb_shared(skb))
                goto out;
 
-       iph = (struct iphdr *)skb->data;
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
                goto out;
+       iph = (struct iphdr *)skb->data;
        if (iph->ihl < 5 || iph->version != 4)
                goto out;
        if (!pskb_may_pull(skb, iph->ihl*4))
                goto out;
+       iph = (struct iphdr *)skb->data;
        if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
                goto out;
 
@@ -579,6 +580,7 @@ int __netpoll_rx(struct sk_buff *skb)
        if (pskb_trim_rcsum(skb, len))
                goto out;
 
+       iph = (struct iphdr *)skb->data;
        if (iph->protocol != IPPROTO_UDP)
                goto out;
 
index 283c0a2..d577199 100644 (file)
@@ -767,7 +767,7 @@ static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
                        break;
                for (i=0; i<nsrcs; i++) {
                        /* skip inactive filters */
-                       if (pmc->sfcount[MCAST_INCLUDE] ||
+                       if (psf->sf_count[MCAST_INCLUDE] ||
                            pmc->sfcount[MCAST_EXCLUDE] !=
                            psf->sf_count[MCAST_EXCLUDE])
                                continue;
index 9cb191e..147ede3 100644 (file)
@@ -913,7 +913,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
 }
 
 static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
-                   char __user *optval, int __user *optlen)
+                   char __user *optval, int __user *optlen, unsigned flags)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        int len;
@@ -962,7 +962,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
 
                msg.msg_control = optval;
                msg.msg_controllen = len;
-               msg.msg_flags = 0;
+               msg.msg_flags = flags;
 
                lock_sock(sk);
                skb = np->pktoptions;
@@ -1222,7 +1222,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
        if(level != SOL_IPV6)
                return -ENOPROTOOPT;
 
-       err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
+       err = do_ipv6_getsockopt(sk, level, optname, optval, optlen, 0);
 #ifdef CONFIG_NETFILTER
        /* we need to exclude all possible ENOPROTOOPTs except default case */
        if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
@@ -1264,7 +1264,8 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
                return compat_mc_getsockopt(sk, level, optname, optval, optlen,
                        ipv6_getsockopt);
 
-       err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
+       err = do_ipv6_getsockopt(sk, level, optname, optval, optlen,
+                                MSG_CMSG_COMPAT);
 #ifdef CONFIG_NETFILTER
        /* we need to exclude all possible ENOPROTOOPTs except default case */
        if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
index 3e6ebcd..ee7839f 100644 (file)
@@ -1059,7 +1059,7 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
                        break;
                for (i=0; i<nsrcs; i++) {
                        /* skip inactive filters */
-                       if (pmc->mca_sfcount[MCAST_INCLUDE] ||
+                       if (psf->sf_count[MCAST_INCLUDE] ||
                            pmc->mca_sfcount[MCAST_EXCLUDE] !=
                            psf->sf_count[MCAST_EXCLUDE])
                                continue;
index 07bf108..00b15ac 100644 (file)
@@ -672,6 +672,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        if (skb->protocol != htons(ETH_P_IPV6))
                goto tx_error;
 
+       if (tos == 1)
+               tos = ipv6_get_dsfield(iph6);
+
        /* ISATAP (RFC4214) - must come before 6to4 */
        if (dev->priv_flags & IFF_ISATAP) {
                struct neighbour *neigh = NULL;
index 866f269..acb4423 100644 (file)
@@ -1012,7 +1012,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
        cancel_work_sync(&local->reconfig_filter);
 
        ieee80211_clear_tx_pending(local);
-       sta_info_stop(local);
        rate_control_deinitialize(local);
 
        if (skb_queue_len(&local->skb_queue) ||
@@ -1024,6 +1023,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 
        destroy_workqueue(local->workqueue);
        wiphy_unregister(local->hw.wiphy);
+       sta_info_stop(local);
        ieee80211_wep_free(local);
        ieee80211_led_exit(local);
        kfree(local->int_scan_req);
index 102fc21..e051398 100644 (file)
@@ -196,8 +196,7 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
 
        skb2->skb_iif = skb->dev->ifindex;
        skb2->dev = dev;
-       dev_queue_xmit(skb2);
-       err = 0;
+       err = dev_queue_xmit(skb2);
 
 out:
        if (err) {
index 24a7740..ffe92ca 100644 (file)
@@ -1965,8 +1965,9 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
         * used_address->name_len is initialized to UINT_MAX so that the first
         * destination address never matches.
         */
-       if (used_address && used_address->name_len == msg_sys->msg_namelen &&
-           !memcmp(&used_address->name, msg->msg_name,
+       if (used_address && msg_sys->msg_name &&
+           used_address->name_len == msg_sys->msg_namelen &&
+           !memcmp(&used_address->name, msg_sys->msg_name,
                    used_address->name_len)) {
                err = sock_sendmsg_nosec(sock, msg_sys, total_len);
                goto out_freectl;
@@ -1978,8 +1979,9 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
         */
        if (used_address && err >= 0) {
                used_address->name_len = msg_sys->msg_namelen;
-               memcpy(&used_address->name, msg->msg_name,
-                      used_address->name_len);
+               if (msg_sys->msg_name)
+                       memcpy(&used_address->name, msg_sys->msg_name,
+                              used_address->name_len);
        }
 
 out_freectl:
index 645437c..c148651 100644 (file)
@@ -616,6 +616,9 @@ int wiphy_register(struct wiphy *wiphy)
        if (res)
                goto out_rm_dev;
 
+       rtnl_lock();
+       rdev->wiphy.registered = true;
+       rtnl_unlock();
        return 0;
 
 out_rm_dev:
@@ -647,6 +650,10 @@ void wiphy_unregister(struct wiphy *wiphy)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       rtnl_lock();
+       rdev->wiphy.registered = false;
+       rtnl_unlock();
+
        rfkill_unregister(rdev->rfkill);
 
        /* protect the device list */
index c6e4ca6..ff57459 100644 (file)
@@ -93,7 +93,8 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
 
        if (rdev->ops->suspend) {
                rtnl_lock();
-               ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
+               if (rdev->wiphy.registered)
+                       ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
                rtnl_unlock();
        }
 
@@ -112,7 +113,8 @@ static int wiphy_resume(struct device *dev)
 
        if (rdev->ops->resume) {
                rtnl_lock();
-               ret = rdev->ops->resume(&rdev->wiphy);
+               if (rdev->wiphy.registered)
+                       ret = rdev->ops->resume(&rdev->wiphy);
                rtnl_unlock();
        }
 
index 9d761c9..3dfc471 100755 (executable)
@@ -2574,7 +2574,8 @@ sub process {
                                } else {
                                        $cast = $cast2;
                                }
-                               WARN("$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . $herecurr);
+                               WARN("MINMAX",
+                                    "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . $herecurr);
                        }
                }
 
index eb2f1e6..4594f33 100755 (executable)
@@ -1389,7 +1389,7 @@ sub vcs_exists {
        warn("$P: No supported VCS found.  Add --nogit to options?\n");
        warn("Using a git repository produces better results.\n");
        warn("Try Linus Torvalds' latest git repository using:\n");
-       warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n");
+       warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git\n");
        $printed_novcs = 1;
     }
     return 0;
index 3fd1a7e..552b97a 100644 (file)
@@ -1073,10 +1073,10 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
        sdev->pcmid = -1;
        list_del(&ldev->list);
        layouts_list_items--;
+       kfree(ldev);
  outnodev:
        of_node_put(sound);
        layout_device = NULL;
-       kfree(ldev);
        return -ENODEV;
 }
 
index 200c9a1..a872d0a 100644 (file)
@@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whitelist[] = {
        0x103c0944, /* HP nc6220 */
        0x103c0934, /* HP nc8220 */
        0x103c006d, /* HP nx9105 */
+       0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */
        0x17340088, /* FSC Scenic-W */
        0 /* end */
 };
index e4d76a2..579fc0d 100644 (file)
@@ -2625,16 +2625,19 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        int err;
 
        snd_azf3328_dbgcallenter();
-       if (dev >= SNDRV_CARDS)
-               return -ENODEV;
+       if (dev >= SNDRV_CARDS) {
+               err = -ENODEV;
+               goto out;
+       }
        if (!enable[dev]) {
                dev++;
-               return -ENOENT;
+               err = -ENOENT;
+               goto out;
        }
 
        err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
        if (err < 0)
-               return err;
+               goto out;
 
        strcpy(card->driver, "AZF3328");
        strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
index be58bf2..2e5876c 100644 (file)
@@ -476,8 +476,8 @@ static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
 
 static const struct alc_config_preset alc268_presets[] = {
        [ALC267_QUANTA_IL1] = {
-               .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc267_quanta_il1_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -492,8 +492,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_3ST] = {
-               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_base_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
                .dac_nids = alc268_dac_nids,
@@ -507,8 +507,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .input_mux = &alc268_capture_source,
        },
        [ALC268_TOSHIBA] = {
-               .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_toshiba_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_toshiba_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -525,8 +525,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER] = {
-               .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_acer_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -543,8 +543,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER_DMIC] = {
-               .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_acer_dmic_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -561,9 +561,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER_ASPIRE_ONE] = {
-               .mixers = { alc268_acer_aspire_one_mixer,
-                           alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc268_acer_aspire_one_mixer, alc268_beep_mixer},
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_aspire_one_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -579,8 +578,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_DELL] = {
-               .mixers = { alc268_dell_mixer, alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc268_dell_mixer, alc268_beep_mixer},
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_dell_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -596,8 +595,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ZEPTO] = {
-               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_base_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_toshiba_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -616,7 +615,8 @@ static const struct alc_config_preset alc268_presets[] = {
        },
 #ifdef CONFIG_SND_DEBUG
        [ALC268_TEST] = {
-               .mixers = { alc268_test_mixer, alc268_capture_mixer },
+               .mixers = { alc268_test_mixer },
+               .cap_mixer = alc268_capture_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_volume_init_verbs,
                                alc268_beep_init_verbs },
index 28ce17d..c34f730 100644 (file)
@@ -144,25 +144,17 @@ static int cea_sampling_frequencies[8] = {
        SNDRV_PCM_RATE_192000,  /* 7: 192000Hz */
 };
 
-static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid,
+static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
                                        int byte_index)
 {
        unsigned int val;
 
        val = snd_hda_codec_read(codec, nid, 0,
                                        AC_VERB_GET_HDMI_ELDD, byte_index);
-
 #ifdef BE_PARANOID
        printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
 #endif
-
-       if ((val & AC_ELDD_ELD_VALID) == 0) {
-               snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n",
-                                                               byte_index);
-               val = 0;
-       }
-
-       return val & AC_ELDD_ELD_DATA;
+       return val;
 }
 
 #define GRAB_BITS(buf, byte, lowbit, bits)             \
@@ -344,11 +336,26 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
        if (!buf)
                return -ENOMEM;
 
-       for (i = 0; i < size; i++)
-               buf[i] = hdmi_get_eld_byte(codec, nid, i);
+       for (i = 0; i < size; i++) {
+               unsigned int val = hdmi_get_eld_data(codec, nid, i);
+               if (!(val & AC_ELDD_ELD_VALID)) {
+                       if (!i) {
+                               snd_printd(KERN_INFO
+                                          "HDMI: invalid ELD data\n");
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       snd_printd(KERN_INFO
+                                 "HDMI: invalid ELD data byte %d\n", i);
+                       val = 0;
+               } else
+                       val &= AC_ELDD_ELD_DATA;
+               buf[i] = val;
+       }
 
        ret = hdmi_update_eld(eld, buf, size);
 
+error:
        kfree(buf);
        return ret;
 }
index 47d6ffc..d6c93d9 100644 (file)
@@ -375,7 +375,7 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx)
 static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
                         unsigned int *idxp)
 {
-       int i;
+       int i, idx;
        hda_nid_t nid;
 
        nid = codec->start_nid;
@@ -384,9 +384,11 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
                type = get_wcaps_type(get_wcaps(codec, nid));
                if (type != AC_WID_AUD_IN)
                        continue;
-               *idxp = snd_hda_get_conn_index(codec, nid, pin, false);
-               if (*idxp >= 0)
+               idx = snd_hda_get_conn_index(codec, nid, pin, false);
+               if (idx >= 0) {
+                       *idxp = idx;
                        return nid;
+               }
        }
        return 0;
 }
index 502fc94..7696d05 100644 (file)
@@ -3348,6 +3348,8 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin,
 
 #define MAX_AUTO_DACS  5
 
+#define DAC_SLAVE_FLAG 0x8000  /* filled dac is a slave */
+
 /* fill analog DAC list from the widget tree */
 static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
 {
@@ -3370,16 +3372,26 @@ static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
 /* fill pin_dac_pair list from the pin and dac list */
 static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins,
                              int num_pins, hda_nid_t *dacs, int *rest,
-                             struct pin_dac_pair *filled, int type)
+                             struct pin_dac_pair *filled, int nums, 
+                             int type)
 {
-       int i, nums;
+       int i, start = nums;
 
-       nums = 0;
-       for (i = 0; i < num_pins; i++) {
+       for (i = 0; i < num_pins; i++, nums++) {
                filled[nums].pin = pins[i];
                filled[nums].type = type;
                filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest);
-               nums++;
+               if (filled[nums].dac) 
+                       continue;
+               if (filled[start].dac && get_connection_index(codec, pins[i], filled[start].dac) >= 0) {
+                       filled[nums].dac = filled[start].dac | DAC_SLAVE_FLAG;
+                       continue;
+               }
+               if (filled[0].dac && get_connection_index(codec, pins[i], filled[0].dac) >= 0) {
+                       filled[nums].dac = filled[0].dac | DAC_SLAVE_FLAG;
+                       continue;
+               }
+               snd_printdd("Failed to find a DAC for pin 0x%x", pins[i]);
        }
        return nums;
 }
@@ -3395,19 +3407,19 @@ static void cx_auto_parse_output(struct hda_codec *codec)
        rest = fill_cx_auto_dacs(codec, dacs);
        /* parse all analog output pins */
        nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs,
-                                 dacs, &rest, spec->dac_info,
-                                 AUTO_PIN_LINE_OUT);
-       nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
-                                 dacs, &rest, spec->dac_info + nums,
-                                 AUTO_PIN_HP_OUT);
-       nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
-                                 dacs, &rest, spec->dac_info + nums,
-                                 AUTO_PIN_SPEAKER_OUT);
+                         dacs, &rest, spec->dac_info, 0,
+                         AUTO_PIN_LINE_OUT);
+       nums = fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
+                         dacs, &rest, spec->dac_info, nums,
+                         AUTO_PIN_HP_OUT);
+       nums = fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
+                         dacs, &rest, spec->dac_info, nums,
+                         AUTO_PIN_SPEAKER_OUT);
        spec->dac_info_filled = nums;
        /* fill multiout struct */
        for (i = 0; i < nums; i++) {
                hda_nid_t dac = spec->dac_info[i].dac;
-               if (!dac)
+               if (!dac || (dac & DAC_SLAVE_FLAG))
                        continue;
                switch (spec->dac_info[i].type) {
                case AUTO_PIN_LINE_OUT:
@@ -3862,7 +3874,7 @@ static void cx_auto_parse_input(struct hda_codec *codec)
        }
        if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items)
                cx_auto_check_auto_mic(codec);
-       if (imux->num_items > 1 && !spec->auto_mic) {
+       if (imux->num_items > 1) {
                for (i = 1; i < imux->num_items; i++) {
                        if (spec->imux_info[i].adc != spec->imux_info[0].adc) {
                                spec->adc_switching = 1;
@@ -4035,6 +4047,8 @@ static void cx_auto_init_output(struct hda_codec *codec)
                nid = spec->dac_info[i].dac;
                if (!nid)
                        nid = spec->multiout.dac_nids[0];
+               else if (nid & DAC_SLAVE_FLAG)
+                       nid &= ~DAC_SLAVE_FLAG;
                select_connection(codec, spec->dac_info[i].pin, nid);
        }
        if (spec->auto_mute) {
@@ -4167,9 +4181,11 @@ static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac,
                             hda_nid_t pin, const char *name, int idx)
 {
        unsigned int caps;
-       caps = query_amp_caps(codec, dac, HDA_OUTPUT);
-       if (caps & AC_AMPCAP_NUM_STEPS)
-               return cx_auto_add_pb_volume(codec, dac, name, idx);
+       if (dac && !(dac & DAC_SLAVE_FLAG)) {
+               caps = query_amp_caps(codec, dac, HDA_OUTPUT);
+               if (caps & AC_AMPCAP_NUM_STEPS)
+                       return cx_auto_add_pb_volume(codec, dac, name, idx);
+       }
        caps = query_amp_caps(codec, pin, HDA_OUTPUT);
        if (caps & AC_AMPCAP_NUM_STEPS)
                return cx_auto_add_pb_volume(codec, pin, name, idx);
@@ -4191,8 +4207,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
        for (i = 0; i < spec->dac_info_filled; i++) {
                const char *label;
                int idx, type;
-               if (!spec->dac_info[i].dac)
-                       continue;
+               hda_nid_t dac = spec->dac_info[i].dac;
                type = spec->dac_info[i].type;
                if (type == AUTO_PIN_LINE_OUT)
                        type = spec->autocfg.line_out_type;
@@ -4211,7 +4226,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
                        idx = num_spk++;
                        break;
                }
-               err = try_add_pb_volume(codec, spec->dac_info[i].dac,
+               err = try_add_pb_volume(codec, dac,
                                        spec->dac_info[i].pin,
                                        label, idx);
                if (err < 0)
index 9a1aa09..7cabd73 100644 (file)
@@ -565,11 +565,11 @@ static void alc_hp_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (!spec->automute)
-               return;
        spec->jack_present =
                detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
                             spec->autocfg.hp_pins);
+       if (!spec->automute)
+               return;
        update_speakers(codec);
 }
 
@@ -578,11 +578,11 @@ static void alc_line_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (!spec->automute || !spec->detect_line)
-               return;
        spec->line_jack_present =
                detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
                             spec->autocfg.line_out_pins);
+       if (!spec->automute || !spec->detect_line)
+               return;
        update_speakers(codec);
 }
 
@@ -1784,6 +1784,7 @@ static const char * const alc_slave_vols[] = {
        "Speaker Playback Volume",
        "Mono Playback Volume",
        "Line-Out Playback Volume",
+       "PCM Playback Volume",
        NULL,
 };
 
@@ -1798,6 +1799,7 @@ static const char * const alc_slave_sws[] = {
        "Mono Playback Switch",
        "IEC958 Playback Switch",
        "Line-Out Playback Switch",
+       "PCM Playback Switch",
        NULL,
 };
 
@@ -3081,16 +3083,22 @@ static void alc_auto_init_multi_out(struct hda_codec *codec)
 static void alc_auto_init_extra_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t pin;
+       hda_nid_t pin, dac;
 
        pin = spec->autocfg.hp_pins[0];
-       if (pin)
-               alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
-                                                 spec->multiout.hp_nid);
+       if (pin) {
+               dac = spec->multiout.hp_nid;
+               if (!dac)
+                       dac = spec->multiout.dac_nids[0];
+               alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+       }
        pin = spec->autocfg.speaker_pins[0];
-       if (pin)
-               alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
-                                       spec->multiout.extra_out_nid[0]);
+       if (pin) {
+               dac = spec->multiout.extra_out_nid[0];
+               if (!dac)
+                       dac = spec->multiout.dac_nids[0];
+               alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+       }
 }
 
 /*
index aa376b5..5145b66 100644 (file)
@@ -673,6 +673,7 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
 static int stac_vrefout_set(struct hda_codec *codec,
                                        hda_nid_t nid, unsigned int new_vref)
 {
@@ -696,6 +697,7 @@ static int stac_vrefout_set(struct hda_codec *codec,
 
        return 1;
 }
+#endif
 
 static unsigned int stac92xx_vref_set(struct hda_codec *codec,
                                        hda_nid_t nid, unsigned int new_vref)
index d6651c0..a118a0f 100644 (file)
@@ -56,7 +56,7 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
 
        switch (params_rate(params)) {
        case 48000:
-               clk = 12288000;
+               clk = 24576000;
                break;
        }
 
index 2374ca5..eedb6f5 100644 (file)
@@ -27,11 +27,6 @@ struct ad193x_priv {
        int sysclk;
 };
 
-/* ad193x register cache & default register settings */
-static const u8 ad193x_reg[AD193X_NUM_REGS] = {
-       0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
-};
-
 /*
  * AD193X volume/mute/de-emphasis etc. controls
  */
@@ -307,7 +302,8 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
        snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg);
 
        reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
-       reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len;
+       reg = (reg & (~AD193X_DAC_WORD_LEN_MASK))
+               | (word_len << AD193X_DAC_WORD_LEN_SHFT);
        snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
 
        reg = snd_soc_read(codec, AD193X_ADC_CTRL1);
@@ -389,9 +385,6 @@ static int ad193x_probe(struct snd_soc_codec *codec)
 
 static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
        .probe =        ad193x_probe,
-       .reg_cache_default = ad193x_reg,
-       .reg_cache_size = AD193X_NUM_REGS,
-       .reg_word_size = sizeof(u16),
 };
 
 #if defined(CONFIG_SPI_MASTER)
index 9747b54..cccc2e8 100644 (file)
@@ -34,7 +34,8 @@
 #define AD193X_DAC_LEFT_HIGH    (1 << 3)
 #define AD193X_DAC_BCLK_INV     (1 << 7)
 #define AD193X_DAC_CTRL2        0x804
-#define AD193X_DAC_WORD_LEN_MASK       0xC
+#define AD193X_DAC_WORD_LEN_SHFT        3
+#define AD193X_DAC_WORD_LEN_MASK        0x18
 #define AD193X_DAC_MASTER_MUTE  1
 #define AD193X_DAC_CHNL_MUTE    0x805
 #define AD193X_DACL1_MUTE       0
@@ -63,7 +64,7 @@
 #define AD193X_ADC_CTRL1        0x80f
 #define AD193X_ADC_SERFMT_MASK         0x60
 #define AD193X_ADC_SERFMT_STEREO       (0 << 5)
-#define AD193X_ADC_SERFMT_TDM          (1 << 2)
+#define AD193X_ADC_SERFMT_TDM          (1 << 5)
 #define AD193X_ADC_SERFMT_AUX          (2 << 5)
 #define AD193X_ADC_WORD_LEN_MASK       0x3
 #define AD193X_ADC_CTRL2        0x810
index 409d89d..fbd7eb9 100644 (file)
@@ -857,6 +857,7 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
        ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret);
+               kfree(sta32x);
                return ret;
        }
 
index 38f38fd..d0003cc 100644 (file)
@@ -778,11 +778,19 @@ static int __devexit wm8750_spi_remove(struct spi_device *spi)
        return 0;
 }
 
+static const struct spi_device_id wm8750_spi_ids[] = {
+       { "wm8750", 0 },
+       { "wm8987", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, wm8750_spi_ids);
+
 static struct spi_driver wm8750_spi_driver = {
        .driver = {
                .name   = "wm8750-codec",
                .owner  = THIS_MODULE,
        },
+       .id_table       = wm8750_spi_ids,
        .probe          = wm8750_spi_probe,
        .remove         = __devexit_p(wm8750_spi_remove),
 };
index 43e3d76..4ad8ebd 100644 (file)
@@ -2046,8 +2046,13 @@ static int wm8903_probe(struct snd_soc_codec *codec)
 /* power down chip */
 static int wm8903_remove(struct snd_soc_codec *codec)
 {
+       struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
+
        wm8903_free_gpio(codec);
        wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       if (wm8903->irq)
+               free_irq(wm8903->irq, codec);
+
        return 0;
 }
 
index 60d740e..1725550 100644 (file)
@@ -2221,6 +2221,8 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
                if (fll) {
+                       try_wait_for_completion(&wm8962->fll_lock);
+
                        snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
                                            WM8962_FLL_ENA, WM8962_FLL_ENA);
                        if (wm8962->irq) {
@@ -2927,10 +2929,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
                                            WM8962_BIAS_ENA | 0x180);
 
                        msleep(5);
-
-                       snd_soc_update_bits(codec, WM8962_CLOCKING2,
-                                           WM8962_CLKREG_OVD,
-                                           WM8962_CLKREG_OVD);
                }
 
                /* VMID 2*250k */
@@ -3288,6 +3286,8 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda);
        snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n);
 
+       try_wait_for_completion(&wm8962->fll_lock);
+
        snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
                            WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
                            WM8962_FLL_ENA, fll1);
@@ -3868,6 +3868,10 @@ static int wm8962_probe(struct snd_soc_codec *codec)
         */
        snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0);
 
+       /* Ensure we have soft control over all registers */
+       snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                           WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
+
        regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
 
        if (pdata) {
index 09e680a..b393f9f 100644 (file)
@@ -2981,6 +2981,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                        wm8994->hubs.dcs_readback_mode = 1;
                        break;
                }
+               break;
 
        case WM8958:
                wm8994->hubs.dcs_readback_mode = 1;
index ab8e9d1..0cdb9d1 100644 (file)
@@ -420,7 +420,7 @@ static const char *sidetone_hpf_text[] = {
 };
 
 static const struct soc_enum sidetone_hpf =
-       SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 6, sidetone_hpf_text);
+       SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 7, sidetone_hpf_text);
 
 static const char *hpf_mode_text[] = {
        "HiFi", "Custom", "Voice"
@@ -988,15 +988,10 @@ SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0),
 SND_SOC_DAPM_PGA("IN1L PGA", WM8996_POWER_MANAGEMENT_2, 5, 0, NULL, 0),
 SND_SOC_DAPM_PGA("IN1R PGA", WM8996_POWER_MANAGEMENT_2, 4, 0, NULL, 0),
 
-SND_SOC_DAPM_MUX("IN1L Mux", SND_SOC_NOPM, 0, 0, &in1_mux),
-SND_SOC_DAPM_MUX("IN1R Mux", SND_SOC_NOPM, 0, 0, &in1_mux),
-SND_SOC_DAPM_MUX("IN2L Mux", SND_SOC_NOPM, 0, 0, &in2_mux),
-SND_SOC_DAPM_MUX("IN2R Mux", SND_SOC_NOPM, 0, 0, &in2_mux),
-
-SND_SOC_DAPM_PGA("IN1L", WM8996_POWER_MANAGEMENT_7, 2, 0, NULL, 0),
-SND_SOC_DAPM_PGA("IN1R", WM8996_POWER_MANAGEMENT_7, 3, 0, NULL, 0),
-SND_SOC_DAPM_PGA("IN2L", WM8996_POWER_MANAGEMENT_7, 6, 0, NULL, 0),
-SND_SOC_DAPM_PGA("IN2R", WM8996_POWER_MANAGEMENT_7, 7, 0, NULL, 0),
+SND_SOC_DAPM_MUX("IN1L Mux", WM8996_POWER_MANAGEMENT_7, 2, 0, &in1_mux),
+SND_SOC_DAPM_MUX("IN1R Mux", WM8996_POWER_MANAGEMENT_7, 3, 0, &in1_mux),
+SND_SOC_DAPM_MUX("IN2L Mux", WM8996_POWER_MANAGEMENT_7, 6, 0, &in2_mux),
+SND_SOC_DAPM_MUX("IN2R Mux", WM8996_POWER_MANAGEMENT_7, 7, 0, &in2_mux),
 
 SND_SOC_DAPM_SUPPLY("DMIC2", WM8996_POWER_MANAGEMENT_7, 9, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("DMIC1", WM8996_POWER_MANAGEMENT_7, 8, 0, NULL, 0),
@@ -1213,6 +1208,16 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
        { "AIF2RX0", NULL, "AIFCLK" },
        { "AIF2RX1", NULL, "AIFCLK" },
 
+       { "AIF1TX0", NULL, "AIFCLK" },
+       { "AIF1TX1", NULL, "AIFCLK" },
+       { "AIF1TX2", NULL, "AIFCLK" },
+       { "AIF1TX3", NULL, "AIFCLK" },
+       { "AIF1TX4", NULL, "AIFCLK" },
+       { "AIF1TX5", NULL, "AIFCLK" },
+
+       { "AIF2TX0", NULL, "AIFCLK" },
+       { "AIF2TX1", NULL, "AIFCLK" },
+
        { "DSP1RXL", NULL, "SYSDSPCLK" },
        { "DSP1RXR", NULL, "SYSDSPCLK" },
        { "DSP2RXL", NULL, "SYSDSPCLK" },
@@ -2106,6 +2111,9 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 
        snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda);
 
+       /* Clear any pending completions (eg, from failed startups) */
+       try_wait_for_completion(&wm8996->fll_lock);
+
        snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1,
                            WM8996_FLL_ENA, WM8996_FLL_ENA);
 
index 56efa0c..099614e 100644 (file)
@@ -385,14 +385,14 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                err = -ENODEV;
-               goto fail;
+               goto fail_free_info;
        }
 
        info->mem = request_mem_region(res->start, resource_size(res),
                                       pdev->name);
        if (!info->mem) {
                err = -EBUSY;
-               goto fail;
+               goto fail_free_info;
        }
 
        info->regs = ioremap(info->mem->start, resource_size(info->mem));
@@ -435,6 +435,7 @@ fail_unmap_mem:
        iounmap(info->regs);
 fail_release_mem:
        release_mem_region(info->mem->start, resource_size(info->mem));
+fail_free_info:
        kfree(info);
 fail:
        return err;
index 732208c..cb50598 100644 (file)
@@ -879,10 +879,12 @@ static struct device_node *find_ssi_node(struct device_node *dma_channel_np)
                 * assume that device_node pointers are a valid comparison.
                 */
                np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0);
+               of_node_put(np);
                if (np == dma_channel_np)
                        return ssi_np;
 
                np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0);
+               of_node_put(np);
                if (np == dma_channel_np)
                        return ssi_np;
        }
index a192979..358f0ba 100644 (file)
@@ -345,8 +345,10 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
        }
 
        machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL);
-       if (!machine_data)
-               return -ENOMEM;
+       if (!machine_data) {
+               ret = -ENOMEM;
+               goto error_alloc;
+       }
 
        machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
        machine_data->dai[0].ops = &mpc8610_hpcd_ops;
@@ -494,7 +496,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
        ret = platform_device_add(sound_device);
        if (ret) {
                dev_err(&pdev->dev, "platform device add failed\n");
-               goto error;
+               goto error_sound;
        }
        dev_set_drvdata(&pdev->dev, sound_device);
 
@@ -502,14 +504,12 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
 
        return 0;
 
+error_sound:
+       platform_device_unregister(sound_device);
 error:
-       of_node_put(codec_np);
-
-       if (sound_device)
-               platform_device_unregister(sound_device);
-
        kfree(machine_data);
-
+error_alloc:
+       of_node_put(codec_np);
        return ret;
 }
 
index 8fa4d5f..fcb862e 100644 (file)
@@ -297,8 +297,10 @@ static int get_dma_channel(struct device_node *ssi_np,
         * dai->platform name should already point to an allocated buffer.
         */
        ret = of_address_to_resource(dma_channel_np, 0, &res);
-       if (ret)
+       if (ret) {
+               of_node_put(dma_channel_np);
                return ret;
+       }
        snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
                 (unsigned long long) res.start, dma_channel_np->name);
 
index a33fc51..8f16cd3 100644 (file)
@@ -424,7 +424,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
        if (!priv->mem) {
                dev_err(&pdev->dev, "request_mem_region failed\n");
                err = -EBUSY;
-               goto error;
+               goto error_alloc;
        }
 
        priv->io = ioremap(priv->mem->start, SZ_16K);
index 30fe0d0..0aa475f 100644 (file)
@@ -514,7 +514,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
        }
 
        /* Set codec bias level */
-       ams_delta_set_bias_level(card, SND_SOC_BIAS_STANDBY);
+       ams_delta_set_bias_level(card, dapm, SND_SOC_BIAS_STANDBY);
 
        /* Add hook switch - can be used to control the codec from userspace
         * even if line discipline fails */
@@ -649,7 +649,9 @@ static void __exit ams_delta_module_exit(void)
                        ams_delta_hook_switch_gpios);
 
        /* Keep modem power on */
-       ams_delta_set_bias_level(&ams_delta_audio_card, SND_SOC_BIAS_STANDBY);
+       ams_delta_set_bias_level(&ams_delta_audio_card,
+                                &ams_delta_audio_card.rtd[0].codec->dapm,
+                                SND_SOC_BIAS_STANDBY);
 
        platform_device_unregister(cx20442_platform_device);
        platform_device_unregister(ams_delta_audio_platform_device);
index 83d213b..62e292f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Nokia Corporation
  *
- * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -402,6 +402,6 @@ static void __exit n810_soc_exit(void)
 module_init(n810_soc_init);
 module_exit(n810_soc_exit);
 
-MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("ALSA SoC Nokia N810");
 MODULE_LICENSE("GPL");
index 07b7723..ebcc2d4 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Nokia Corporation
  *
- * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
  *          Peter Ujfalusi <peter.ujfalusi@ti.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -780,6 +780,6 @@ static void __exit snd_omap_mcbsp_exit(void)
 }
 module_exit(snd_omap_mcbsp_exit);
 
-MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("OMAP I2S SoC Interface");
 MODULE_LICENSE("GPL");
index 9a7dedd..65cde9d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Nokia Corporation
  *
- * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
  *          Peter Ujfalusi <peter.ujfalusi@ti.com>
  *
  * This program is free software; you can redistribute it and/or
index b2f5751..9b5c88a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Nokia Corporation
  *
- * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
  *          Peter Ujfalusi <peter.ujfalusi@ti.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -436,6 +436,6 @@ static void __exit snd_omap_pcm_exit(void)
 }
 module_exit(snd_omap_pcm_exit);
 
-MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("OMAP PCM DMA module");
 MODULE_LICENSE("GPL");
index a0ed1db..f95fe30 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Nokia Corporation
  *
- * Contact: Jarkko Nikula <jhnikula@gmail.com>
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
  *          Peter Ujfalusi <peter.ujfalusi@ti.com>
  *
  * This program is free software; you can redistribute it and/or
index 0aae998..893300a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Contact: Peter Ujfalusi <peter.ujfalusi@ti.com>
  *          Eduardo Valentin <eduardo.valentin@nokia.com>
- *          Jarkko Nikula <jhnikula@gmail.com>
+ *          Jarkko Nikula <jarkko.nikula@bitmer.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index b99091f..65f980e 100644 (file)
@@ -185,6 +185,7 @@ config SND_SOC_SPEYSIDE
        select SND_SAMSUNG_I2S
        select SND_SOC_WM8996
        select SND_SOC_WM9081
+       select SND_SOC_WM1250_EV1
 
 config SND_SOC_SPEYSIDE_WM8962
        tristate "Audio support for Wolfson Speyside with WM8962"
index 9eb3b12..8509d3c 100644 (file)
@@ -1,5 +1,6 @@
 # S3c24XX Platform Support
 snd-soc-s3c24xx-objs := dma.o
+snd-soc-idma-objs := idma.o
 snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
 snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
 snd-soc-ac97-objs := ac97.o
@@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
 obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o
 obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o
 obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
+obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o
 
 # S3C24XX Machine Support
 snd-soc-jive-wm8750-objs := jive_wm8750.o
index 241f55d..c6c6589 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/types.h>
 #include <linux/gpio.h>
 
 #include <sound/soc.h>
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
new file mode 100644 (file)
index 0000000..ebde074
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ * sound/soc/samsung/idma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * I2S0's Internal DMA driver
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "i2s.h"
+#include "idma.h"
+#include "dma.h"
+#include "i2s-regs.h"
+
+#define ST_RUNNING             (1<<0)
+#define ST_OPENED              (1<<1)
+
+static const struct snd_pcm_hardware idma_hardware = {
+       .info = SNDRV_PCM_INFO_INTERLEAVED |
+                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                   SNDRV_PCM_INFO_MMAP |
+                   SNDRV_PCM_INFO_MMAP_VALID |
+                   SNDRV_PCM_INFO_PAUSE |
+                   SNDRV_PCM_INFO_RESUME,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE |
+                   SNDRV_PCM_FMTBIT_U16_LE |
+                   SNDRV_PCM_FMTBIT_S24_LE |
+                   SNDRV_PCM_FMTBIT_U24_LE |
+                   SNDRV_PCM_FMTBIT_U8 |
+                   SNDRV_PCM_FMTBIT_S8,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = MAX_IDMA_BUFFER,
+       .period_bytes_min = 128,
+       .period_bytes_max = MAX_IDMA_PERIOD,
+       .periods_min = 1,
+       .periods_max = 2,
+};
+
+struct idma_ctrl {
+       spinlock_t      lock;
+       int             state;
+       dma_addr_t      start;
+       dma_addr_t      pos;
+       dma_addr_t      end;
+       dma_addr_t      period;
+       dma_addr_t      periodsz;
+       void            *token;
+       void            (*cb)(void *dt, int bytes_xfer);
+};
+
+static struct idma_info {
+       spinlock_t      lock;
+       void             __iomem  *regs;
+       dma_addr_t      lp_tx_addr;
+} idma;
+
+static void idma_getpos(dma_addr_t *src)
+{
+       *src = idma.lp_tx_addr +
+               (readl(idma.regs + I2STRNCNT) & 0xffffff) * 4;
+}
+
+static int idma_enqueue(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct idma_ctrl *prtd = substream->runtime->private_data;
+       u32 val;
+
+       spin_lock(&prtd->lock);
+       prtd->token = (void *) substream;
+       spin_unlock(&prtd->lock);
+
+       /* Internal DMA Level0 Interrupt Address */
+       val = idma.lp_tx_addr + prtd->periodsz;
+       writel(val, idma.regs + I2SLVL0ADDR);
+
+       /* Start address0 of I2S internal DMA operation. */
+       val = idma.lp_tx_addr;
+       writel(val, idma.regs + I2SSTR0);
+
+       /*
+        * Transfer block size for I2S internal DMA.
+        * Should decide transfer size before start dma operation
+        */
+       val = readl(idma.regs + I2SSIZE);
+       val &= ~(I2SSIZE_TRNMSK << I2SSIZE_SHIFT);
+       val |= (((runtime->dma_bytes >> 2) &
+                       I2SSIZE_TRNMSK) << I2SSIZE_SHIFT);
+       writel(val, idma.regs + I2SSIZE);
+
+       val = readl(idma.regs + I2SAHB);
+       val |= AHB_INTENLVL0;
+       writel(val, idma.regs + I2SAHB);
+
+       return 0;
+}
+
+static void idma_setcallbk(struct snd_pcm_substream *substream,
+                               void (*cb)(void *, int))
+{
+       struct idma_ctrl *prtd = substream->runtime->private_data;
+
+       spin_lock(&prtd->lock);
+       prtd->cb = cb;
+       spin_unlock(&prtd->lock);
+}
+
+static void idma_control(int op)
+{
+       u32 val = readl(idma.regs + I2SAHB);
+
+       spin_lock(&idma.lock);
+
+       switch (op) {
+       case LPAM_DMA_START:
+               val |= (AHB_INTENLVL0 | AHB_DMAEN);
+               break;
+       case LPAM_DMA_STOP:
+               val &= ~(AHB_INTENLVL0 | AHB_DMAEN);
+               break;
+       default:
+               spin_unlock(&idma.lock);
+               return;
+       }
+
+       writel(val, idma.regs + I2SAHB);
+       spin_unlock(&idma.lock);
+}
+
+static void idma_done(void *id, int bytes_xfer)
+{
+       struct snd_pcm_substream *substream = id;
+       struct idma_ctrl *prtd = substream->runtime->private_data;
+
+       if (prtd && (prtd->state & ST_RUNNING))
+               snd_pcm_period_elapsed(substream);
+}
+
+static int idma_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct idma_ctrl *prtd = substream->runtime->private_data;
+       u32 mod = readl(idma.regs + I2SMOD);
+       u32 ahb = readl(idma.regs + I2SAHB);
+
+       ahb |= (AHB_DMARLD | AHB_INTMASK);
+       mod |= MOD_TXS_IDMA;
+       writel(ahb, idma.regs + I2SAHB);
+       writel(mod, idma.regs + I2SMOD);
+
+       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+       runtime->dma_bytes = params_buffer_bytes(params);
+
+       prtd->start = prtd->pos = runtime->dma_addr;
+       prtd->period = params_periods(params);
+       prtd->periodsz = params_period_bytes(params);
+       prtd->end = runtime->dma_addr + runtime->dma_bytes;
+
+       idma_setcallbk(substream, idma_done);
+
+       return 0;
+}
+
+static int idma_hw_free(struct snd_pcm_substream *substream)
+{
+       snd_pcm_set_runtime_buffer(substream, NULL);
+
+       return 0;
+}
+
+static int idma_prepare(struct snd_pcm_substream *substream)
+{
+       struct idma_ctrl *prtd = substream->runtime->private_data;
+
+       prtd->pos = prtd->start;
+
+       /* flush the DMA channel */
+       idma_control(LPAM_DMA_STOP);
+       idma_enqueue(substream);
+
+       return 0;
+}
+
+static int idma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct idma_ctrl *prtd = substream->runtime->private_data;
+       int ret = 0;
+
+       spin_lock(&prtd->lock);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               prtd->state |= ST_RUNNING;
+               idma_control(LPAM_DMA_START);
+               break;
+
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               prtd->state &= ~ST_RUNNING;
+               idma_control(LPAM_DMA_STOP);
+               break;
+
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       spin_unlock(&prtd->lock);
+
+       return ret;
+}
+
+static snd_pcm_uframes_t
+       idma_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct idma_ctrl *prtd = runtime->private_data;
+       dma_addr_t src;
+       unsigned long res;
+
+       spin_lock(&prtd->lock);
+
+       idma_getpos(&src);
+       res = src - prtd->start;
+
+       spin_unlock(&prtd->lock);
+
+       return bytes_to_frames(substream->runtime, res);
+}
+
+static int idma_mmap(struct snd_pcm_substream *substream,
+       struct vm_area_struct *vma)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       unsigned long size, offset;
+       int ret;
+
+       /* From snd_pcm_lib_mmap_iomem */
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       vma->vm_flags |= VM_IO;
+       size = vma->vm_end - vma->vm_start;
+       offset = vma->vm_pgoff << PAGE_SHIFT;
+       ret = io_remap_pfn_range(vma, vma->vm_start,
+                       (runtime->dma_addr + offset) >> PAGE_SHIFT,
+                       size, vma->vm_page_prot);
+
+       return ret;
+}
+
+static irqreturn_t iis_irq(int irqno, void *dev_id)
+{
+       struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id;
+       u32 iiscon, iisahb, val, addr;
+
+       iisahb  = readl(idma.regs + I2SAHB);
+       iiscon  = readl(idma.regs + I2SCON);
+
+       val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0;
+
+       if (val) {
+               iisahb |= val;
+               writel(iisahb, idma.regs + I2SAHB);
+
+               addr = readl(idma.regs + I2SLVL0ADDR) - idma.lp_tx_addr;
+               addr += prtd->periodsz;
+               addr %= (prtd->end - prtd->start);
+               addr += idma.lp_tx_addr;
+
+               writel(addr, idma.regs + I2SLVL0ADDR);
+
+               if (prtd->cb)
+                       prtd->cb(prtd->token, prtd->period);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int idma_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct idma_ctrl *prtd;
+       int ret;
+
+       snd_soc_set_runtime_hwparams(substream, &idma_hardware);
+
+       prtd = kzalloc(sizeof(struct idma_ctrl), GFP_KERNEL);
+       if (prtd == NULL)
+               return -ENOMEM;
+
+       ret = request_irq(IRQ_I2S0, iis_irq, 0, "i2s", prtd);
+       if (ret < 0) {
+               pr_err("fail to claim i2s irq , ret = %d\n", ret);
+               kfree(prtd);
+               return ret;
+       }
+
+       spin_lock_init(&prtd->lock);
+
+       runtime->private_data = prtd;
+
+       return 0;
+}
+
+static int idma_close(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct idma_ctrl *prtd = runtime->private_data;
+
+       free_irq(IRQ_I2S0, prtd);
+
+       if (!prtd)
+               pr_err("idma_close called with prtd == NULL\n");
+
+       kfree(prtd);
+
+       return 0;
+}
+
+static struct snd_pcm_ops idma_ops = {
+       .open           = idma_open,
+       .close          = idma_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .trigger        = idma_trigger,
+       .pointer        = idma_pointer,
+       .mmap           = idma_mmap,
+       .hw_params      = idma_hw_params,
+       .hw_free        = idma_hw_free,
+       .prepare        = idma_prepare,
+};
+
+static void idma_free(struct snd_pcm *pcm)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_dma_buffer *buf;
+
+       substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+       if (!substream)
+               return;
+
+       buf = &substream->dma_buffer;
+       if (!buf->area)
+               return;
+
+       iounmap(buf->area);
+
+       buf->area = NULL;
+       buf->addr = 0;
+}
+
+static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
+{
+       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+       struct snd_dma_buffer *buf = &substream->dma_buffer;
+
+       buf->dev.dev = pcm->card->dev;
+       buf->private_data = NULL;
+
+       /* Assign PCM buffer pointers */
+       buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
+       buf->addr = idma.lp_tx_addr;
+       buf->bytes = idma_hardware.buffer_bytes_max;
+       buf->area = (unsigned char *)ioremap(buf->addr, buf->bytes);
+
+       return 0;
+}
+
+static u64 idma_mask = DMA_BIT_MASK(32);
+
+static int idma_new(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_card *card = rtd->card->snd_card;
+       struct snd_soc_dai *dai = rtd->cpu_dai;
+       struct snd_pcm *pcm = rtd->pcm;
+       int ret = 0;
+
+       if (!card->dev->dma_mask)
+               card->dev->dma_mask = &idma_mask;
+       if (!card->dev->coherent_dma_mask)
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+       if (dai->driver->playback.channels_min)
+               ret = preallocate_idma_buffer(pcm,
+                               SNDRV_PCM_STREAM_PLAYBACK);
+
+       return ret;
+}
+
+void idma_reg_addr_init(void *regs, dma_addr_t addr)
+{
+       spin_lock_init(&idma.lock);
+       idma.regs = regs;
+       idma.lp_tx_addr = addr;
+}
+
+struct snd_soc_platform_driver asoc_idma_platform = {
+       .ops = &idma_ops,
+       .pcm_new = idma_new,
+       .pcm_free = idma_free,
+};
+
+static int __devinit asoc_idma_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform);
+}
+
+static int __devexit asoc_idma_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver asoc_idma_driver = {
+       .driver = {
+               .name = "samsung-idma",
+               .owner = THIS_MODULE,
+       },
+
+       .probe = asoc_idma_platform_probe,
+       .remove = __devexit_p(asoc_idma_platform_remove),
+};
+
+static int __init asoc_idma_init(void)
+{
+       return platform_driver_register(&asoc_idma_driver);
+}
+module_init(asoc_idma_init);
+
+static void __exit asoc_idma_exit(void)
+{
+       platform_driver_unregister(&asoc_idma_driver);
+}
+module_exit(asoc_idma_exit);
+
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
+MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h
new file mode 100644 (file)
index 0000000..4827321
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * sound/soc/samsung/idma.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *             http://www.samsung.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __SND_SOC_SAMSUNG_IDMA_H_
+#define __SND_SOC_SAMSUNG_IDMA_H_
+
+extern void idma_reg_addr_init(void *regs, dma_addr_t addr);
+
+/* dma_state */
+#define LPAM_DMA_STOP  0
+#define LPAM_DMA_START 1
+
+#define MAX_IDMA_PERIOD (128 * 1024)
+#define MAX_IDMA_BUFFER (160 * 1024)
+
+#endif /* __SND_SOC_SAMSUNG_IDMA_H_ */
index 3b53ad5..14eb6ea 100644 (file)
@@ -131,7 +131,7 @@ static struct snd_soc_dai_link jive_dai = {
        .cpu_dai_name   = "s3c2412-i2s",
        .codec_dai_name = "wm8750-hifi",
        .platform_name  = "samsung-audio",
-       .codec_name     = "wm8750-codec.0-0x1a",
+       .codec_name     = "wm8750-codec.0-001a",
        .init           = jive_wm8750_init,
        .ops            = &jive_ops,
 };
index 1e574a5..bc8c167 100644 (file)
@@ -17,6 +17,7 @@
  *
  */
 
+#include <linux/types.h>
 #include <linux/gpio.h>
 
 #include <sound/soc.h>
index 8ac42bf..72535f2 100644 (file)
@@ -23,6 +23,9 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
        struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
        int ret;
 
+       if (dapm->dev != codec_dai->dev)
+               return 0;
+
        switch (level) {
        case SND_SOC_BIAS_PREPARE:
                if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
@@ -37,7 +40,7 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
                                                     44100 * 256,
                                                     SND_SOC_CLOCK_IN);
                        if (ret < 0) {
-                               pr_err("Failed to set SYSCLK: %d\n");
+                               pr_err("Failed to set SYSCLK: %d\n", ret);
                                return ret;
                        }
                }
@@ -57,6 +60,9 @@ static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
        struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
        int ret;
 
+       if (dapm->dev != codec_dai->dev)
+               return 0;
+
        switch (level) {
        case SND_SOC_BIAS_STANDBY:
                ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
index 83ad8ca..b085d8e 100644 (file)
@@ -1913,7 +1913,7 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 
        if (prefix) {
                name_len = strlen(long_name) + strlen(prefix) + 2;
-               name = kmalloc(name_len, GFP_ATOMIC);
+               name = kmalloc(name_len, GFP_KERNEL);
                if (!name)
                        return NULL;
 
index cca490c..a62f7dd 100644 (file)
@@ -205,6 +205,25 @@ static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
 #define snd_soc_16_8_read_i2c NULL
 #endif
 
+#if defined(CONFIG_SPI_MASTER)
+static unsigned int snd_soc_16_8_read_spi(struct snd_soc_codec *codec,
+                                         unsigned int r)
+{
+       struct spi_device *spi = codec->control_data;
+
+       const u16 reg = cpu_to_be16(r | 0x100);
+       u8 data;
+       int ret;
+
+       ret = spi_write_then_read(spi, &reg, 2, &data, 1);
+       if (ret < 0)
+               return 0;
+       return data;
+}
+#else
+#define snd_soc_16_8_read_spi NULL
+#endif
+
 static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
                              unsigned int value)
 {
@@ -295,6 +314,7 @@ static struct {
        int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
        unsigned int (*read)(struct snd_soc_codec *, unsigned int);
        unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
+       unsigned int (*spi_read)(struct snd_soc_codec *, unsigned int);
 } io_types[] = {
        {
                .addr_bits = 4, .data_bits = 12,
@@ -318,6 +338,7 @@ static struct {
                .addr_bits = 16, .data_bits = 8,
                .write = snd_soc_16_8_write,
                .i2c_read = snd_soc_16_8_read_i2c,
+               .spi_read = snd_soc_16_8_read_spi,
        },
        {
                .addr_bits = 16, .data_bits = 16,
@@ -383,6 +404,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 #ifdef CONFIG_SPI_MASTER
                codec->hw_write = do_spi_write;
 #endif
+               if (io_types[i].spi_read)
+                       codec->hw_read = io_types[i].spi_read;
 
                codec->control_data = container_of(codec->dev,
                                                   struct spi_device,
index 7c17b98..38b0013 100644 (file)
@@ -327,7 +327,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
                                              IRQF_TRIGGER_FALLING,
                                              gpios[i].name,
                                              &gpios[i]);
-               if (ret)
+               if (ret < 0)
                        goto err;
 
                if (gpios[i].wake) {
index b575939..2879c88 100644 (file)
@@ -290,6 +290,9 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        codec_dai->active--;
        codec->active--;
 
+       if (!cpu_dai->active && !codec_dai->active)
+               rtd->rate = 0;
+
        /* Muting the DAC suppresses artifacts caused during digital
         * shutdown, for example from stopping clocks.
         */
index ff86e5e..c7cfd96 100644 (file)
@@ -309,9 +309,14 @@ static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 
 static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 {
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
+       struct snd_pcm_substream *substream;
+       struct snd_dma_buffer *buf;
+
+       substream = pcm->streams[stream].substream;
+       if (!substream)
+               return;
 
+       buf = &substream->dma_buffer;
        if (!buf->area)
                return;
 
index a42e9ac..be27f1d 100644 (file)
@@ -56,6 +56,7 @@
 #define GPIO_HP_MUTE    BIT(1)
 #define GPIO_INT_MIC_EN BIT(2)
 #define GPIO_EXT_MIC_EN BIT(3)
+#define GPIO_HP_DET     BIT(4)
 
 struct tegra_wm8903 {
        struct tegra_asoc_utils_data util_data;
@@ -304,6 +305,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
                snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
                                        1,
                                        &tegra_wm8903_hp_jack_gpio);
+               machine->gpio_requested |= GPIO_HP_DET;
        }
 
        snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
@@ -317,7 +319,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
 
        /* FIXME: Calculate automatically based on DAPM routes? */
-       if (!machine_is_harmony() && !machine_is_ventana())
+       if (!machine_is_harmony())
                snd_soc_dapm_nc_pin(dapm, "IN1L");
        if (!machine_is_seaboard() && !machine_is_aebl())
                snd_soc_dapm_nc_pin(dapm, "IN1R");
@@ -393,7 +395,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, card);
        snd_soc_card_set_drvdata(card, machine);
 
-       if (machine_is_harmony() || machine_is_ventana()) {
+       if (machine_is_harmony()) {
                card->dapm_routes = harmony_audio_map;
                card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
        } else if (machine_is_seaboard()) {
@@ -429,10 +431,10 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
        struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
        struct tegra_wm8903_platform_data *pdata = machine->pdata;
 
-       snd_soc_unregister_card(card);
-
-       tegra_asoc_utils_fini(&machine->util_data);
-
+       if (machine->gpio_requested & GPIO_HP_DET)
+               snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack,
+                                       1,
+                                       &tegra_wm8903_hp_jack_gpio);
        if (machine->gpio_requested & GPIO_EXT_MIC_EN)
                gpio_free(pdata->gpio_ext_mic_en);
        if (machine->gpio_requested & GPIO_INT_MIC_EN)
@@ -441,6 +443,11 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
                gpio_free(pdata->gpio_hp_mute);
        if (machine->gpio_requested & GPIO_SPKR_EN)
                gpio_free(pdata->gpio_spkr_en);
+       machine->gpio_requested = 0;
+
+       snd_soc_unregister_card(card);
+
+       tegra_asoc_utils_fini(&machine->util_data);
 
        kfree(machine);
 
index d0d493c..2cf87f5 100644 (file)
@@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_caiaqdev *dev)
 
        for (i = 0; i < N_URBS; i++) {
                usb_kill_urb(dev->data_urbs_in[i]);
-               usb_kill_urb(dev->data_urbs_out[i]);
+
+               if (test_bit(i, &dev->outurb_active_mask))
+                       usb_kill_urb(dev->data_urbs_out[i]);
        }
+
+       dev->outurb_active_mask = 0;
 }
 
 static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
@@ -612,8 +616,9 @@ static void read_completed(struct urb *urb)
 {
        struct snd_usb_caiaq_cb_info *info = urb->context;
        struct snd_usb_caiaqdev *dev;
-       struct urb *out;
-       int frame, len, send_it = 0, outframe = 0;
+       struct urb *out = NULL;
+       int i, frame, len, send_it = 0, outframe = 0;
+       size_t offset = 0;
 
        if (urb->status || !info)
                return;
@@ -623,7 +628,17 @@ static void read_completed(struct urb *urb)
        if (!dev->streaming)
                return;
 
-       out = dev->data_urbs_out[info->index];
+       /* find an unused output urb that is unused */
+       for (i = 0; i < N_URBS; i++)
+               if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) {
+                       out = dev->data_urbs_out[i];
+                       break;
+               }
+
+       if (!out) {
+               log("Unable to find an output urb to use\n");
+               goto requeue;
+       }
 
        /* read the recently received packet and send back one which has
         * the same layout */
@@ -634,7 +649,8 @@ static void read_completed(struct urb *urb)
                len = urb->iso_frame_desc[outframe].actual_length;
                out->iso_frame_desc[outframe].length = len;
                out->iso_frame_desc[outframe].actual_length = 0;
-               out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
+               out->iso_frame_desc[outframe].offset = offset;
+               offset += len;
 
                if (len > 0) {
                        spin_lock(&dev->spinlock);
@@ -650,11 +666,15 @@ static void read_completed(struct urb *urb)
        }
 
        if (send_it) {
-               out->number_of_packets = FRAMES_PER_URB;
+               out->number_of_packets = outframe;
                out->transfer_flags = URB_ISO_ASAP;
                usb_submit_urb(out, GFP_ATOMIC);
+       } else {
+               struct snd_usb_caiaq_cb_info *oinfo = out->context;
+               clear_bit(oinfo->index, &dev->outurb_active_mask);
        }
 
+requeue:
        /* re-submit inbound urb */
        for (frame = 0; frame < FRAMES_PER_URB; frame++) {
                urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame;
@@ -676,6 +696,8 @@ static void write_completed(struct urb *urb)
                dev->output_running = 1;
                wake_up(&dev->prepare_wait_queue);
        }
+
+       clear_bit(info->index, &dev->outurb_active_mask);
 }
 
 static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
@@ -827,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
        if (!dev->data_cb_info)
                return -ENOMEM;
 
+       dev->outurb_active_mask = 0;
+       BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8));
+
        for (i = 0; i < N_URBS; i++) {
                dev->data_cb_info[i].dev = dev;
                dev->data_cb_info[i].index = i;
index b2b3101..3f9c633 100644 (file)
@@ -96,6 +96,7 @@ struct snd_usb_caiaqdev {
        int input_panic, output_panic, warned;
        char *audio_in_buf, *audio_out_buf;
        unsigned int samplerates, bpp;
+       unsigned long outurb_active_mask;
 
        struct snd_pcm_substream *sub_playback[MAX_STREAMS];
        struct snd_pcm_substream *sub_capture[MAX_STREAMS];
index c04d7c7..cdd19d7 100644 (file)
@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const struct usbmix_name_map *p,
        if (p && p->dB) {
                cval->dBmin = p->dB->min;
                cval->dBmax = p->dB->max;
+               cval->initialized = 1;
        }
 }
 
@@ -1092,7 +1093,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                                " Switch" : " Volume");
                if (control == UAC_FU_VOLUME) {
                        check_mapped_dB(map, cval);
-                       if (cval->dBmin < cval->dBmax) {
+                       if (cval->dBmin < cval->dBmax || !cval->initialized) {
                                kctl->tlv.c = mixer_vol_tlv;
                                kctl->vd[0].access |= 
                                        SNDRV_CTL_ELEM_ACCESS_TLV_READ |
index 4d4f865..a42e3ef 100644 (file)
@@ -1707,6 +1707,40 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       USB_DEVICE(0x0582, 0x0130),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "BOSS", */
+               /* .product_name = "MICRO BR-80", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 /* Guillemot devices */
 {
index 5f2a5c7..710ae3d 100644 (file)
@@ -134,10 +134,18 @@ static int opt_show_lines(const struct option *opt __used,
 {
        int ret = 0;
 
-       if (str)
-               ret = parse_line_range_desc(str, &params.line_range);
-       INIT_LIST_HEAD(&params.line_range.line_list);
+       if (!str)
+               return 0;
+
+       if (params.show_lines) {
+               pr_warning("Warning: more than one --line options are"
+                          " detected. Only the first one is valid.\n");
+               return 0;
+       }
+
        params.show_lines = true;
+       ret = parse_line_range_desc(str, &params.line_range);
+       INIT_LIST_HEAD(&params.line_range.line_list);
 
        return ret;
 }
index f6426b4..6b0519f 100644 (file)
@@ -45,7 +45,7 @@ static int                    freq                            =   1000;
 static int                     output;
 static int                     pipe_output                     =      0;
 static const char              *output_name                    = NULL;
-static int                     group                           =      0;
+static bool                    group                           =  false;
 static int                     realtime_prio                   =      0;
 static bool                    nodelay                         =  false;
 static bool                    raw_samples                     =  false;
@@ -753,6 +753,8 @@ const struct option record_options[] = {
                    "child tasks do not inherit counters"),
        OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
        OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
+       OPT_BOOLEAN(0, "group", &group,
+                   "put the counters into a counter group"),
        OPT_BOOLEAN('g', "call-graph", &call_graph,
                    "do call-graph (stack chain/backtrace) recording"),
        OPT_INCR('v', "verbose", &verbose,
index 1ad04ce..5deb17d 100644 (file)
@@ -193,6 +193,7 @@ static int                  big_num_opt                     =  -1;
 static const char              *cpu_list;
 static const char              *csv_sep                        = NULL;
 static bool                    csv_output                      = false;
+static bool                    group                           = false;
 
 static volatile int done = 0;
 
@@ -280,14 +281,14 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
        attr->inherit = !no_inherit;
 
        if (system_wide)
-               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);
+               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, group);
 
        if (target_pid == -1 && target_tid == -1) {
                attr->disabled = 1;
                attr->enable_on_exec = 1;
        }
 
-       return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
+       return perf_evsel__open_per_thread(evsel, evsel_list->threads, group);
 }
 
 /*
@@ -1043,6 +1044,8 @@ static const struct option options[] = {
                    "stat events on existing thread id"),
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
                    "system-wide collection from all CPUs"),
+       OPT_BOOLEAN('g', "group", &group,
+                   "put the counters into a counter group"),
        OPT_BOOLEAN('c', "scale", &scale,
                    "scale/normalize counters"),
        OPT_INCR('v', "verbose", &verbose,
index fddf40f..ee51e9b 100644 (file)
@@ -96,6 +96,39 @@ int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
        return *lineno ?: -ENOENT;
 }
 
+static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
+
+/**
+ * cu_walk_functions_at - Walk on function DIEs at given address
+ * @cu_die: A CU DIE
+ * @addr: An address
+ * @callback: A callback which called with found DIEs
+ * @data: A user data
+ *
+ * Walk on function DIEs at given @addr in @cu_die. Passed DIEs
+ * should be subprogram or inlined-subroutines.
+ */
+int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
+                   int (*callback)(Dwarf_Die *, void *), void *data)
+{
+       Dwarf_Die die_mem;
+       Dwarf_Die *sc_die;
+       int ret = -ENOENT;
+
+       /* Inlined function could be recursive. Trace it until fail */
+       for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
+            sc_die != NULL;
+            sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
+                                    &die_mem)) {
+               ret = callback(sc_die, data);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+
+}
+
 /**
  * die_compare_name - Compare diename and tname
  * @dw_die: a DIE
@@ -198,6 +231,19 @@ static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
        return 0;
 }
 
+/* Get attribute and translate it as a sdata */
+static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
+                             Dwarf_Sword *result)
+{
+       Dwarf_Attribute attr;
+
+       if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
+           dwarf_formsdata(&attr, result) != 0)
+               return -ENOENT;
+
+       return 0;
+}
+
 /**
  * die_is_signed_type - Check whether a type DIE is signed or not
  * @tp_die: a DIE of a type
@@ -250,6 +296,50 @@ int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
        return 0;
 }
 
+/* Get the call file index number in CU DIE */
+static int die_get_call_fileno(Dwarf_Die *in_die)
+{
+       Dwarf_Sword idx;
+
+       if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
+               return (int)idx;
+       else
+               return -ENOENT;
+}
+
+/* Get the declared file index number in CU DIE */
+static int die_get_decl_fileno(Dwarf_Die *pdie)
+{
+       Dwarf_Sword idx;
+
+       if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
+               return (int)idx;
+       else
+               return -ENOENT;
+}
+
+/**
+ * die_get_call_file - Get callsite file name of inlined function instance
+ * @in_die: a DIE of an inlined function instance
+ *
+ * Get call-site file name of @in_die. This means from which file the inline
+ * function is called.
+ */
+const char *die_get_call_file(Dwarf_Die *in_die)
+{
+       Dwarf_Die cu_die;
+       Dwarf_Files *files;
+       int idx;
+
+       idx = die_get_call_fileno(in_die);
+       if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
+           dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
+               return NULL;
+
+       return dwarf_filesrc(files, idx, NULL, NULL);
+}
+
+
 /**
  * die_find_child - Generic DIE search function in DIE tree
  * @rt_die: a root DIE
@@ -374,9 +464,78 @@ Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
        return die_mem;
 }
 
+struct __instance_walk_param {
+       void    *addr;
+       int     (*callback)(Dwarf_Die *, void *);
+       void    *data;
+       int     retval;
+};
+
+static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
+{
+       struct __instance_walk_param *iwp = data;
+       Dwarf_Attribute attr_mem;
+       Dwarf_Die origin_mem;
+       Dwarf_Attribute *attr;
+       Dwarf_Die *origin;
+       int tmp;
+
+       attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
+       if (attr == NULL)
+               return DIE_FIND_CB_CONTINUE;
+
+       origin = dwarf_formref_die(attr, &origin_mem);
+       if (origin == NULL || origin->addr != iwp->addr)
+               return DIE_FIND_CB_CONTINUE;
+
+       /* Ignore redundant instances */
+       if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
+               dwarf_decl_line(origin, &tmp);
+               if (die_get_call_lineno(inst) == tmp) {
+                       tmp = die_get_decl_fileno(origin);
+                       if (die_get_call_fileno(inst) == tmp)
+                               return DIE_FIND_CB_CONTINUE;
+               }
+       }
+
+       iwp->retval = iwp->callback(inst, iwp->data);
+
+       return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
+}
+
+/**
+ * die_walk_instances - Walk on instances of given DIE
+ * @or_die: an abstract original DIE
+ * @callback: a callback function which is called with instance DIE
+ * @data: user data
+ *
+ * Walk on the instances of give @in_die. @in_die must be an inlined function
+ * declartion. This returns the return value of @callback if it returns
+ * non-zero value, or -ENOENT if there is no instance.
+ */
+int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
+                      void *data)
+{
+       Dwarf_Die cu_die;
+       Dwarf_Die die_mem;
+       struct __instance_walk_param iwp = {
+               .addr = or_die->addr,
+               .callback = callback,
+               .data = data,
+               .retval = -ENOENT,
+       };
+
+       if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
+               return -ENOENT;
+
+       die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
+
+       return iwp.retval;
+}
+
 /* Line walker internal parameters */
 struct __line_walk_param {
-       const char *fname;
+       bool recursive;
        line_walk_callback_t callback;
        void *data;
        int retval;
@@ -385,39 +544,56 @@ struct __line_walk_param {
 static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
 {
        struct __line_walk_param *lw = data;
-       Dwarf_Addr addr;
+       Dwarf_Addr addr = 0;
+       const char *fname;
        int lineno;
 
        if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
+               fname = die_get_call_file(in_die);
                lineno = die_get_call_lineno(in_die);
-               if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
-                       lw->retval = lw->callback(lw->fname, lineno, addr,
-                                                 lw->data);
+               if (fname && lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
+                       lw->retval = lw->callback(fname, lineno, addr, lw->data);
                        if (lw->retval != 0)
                                return DIE_FIND_CB_END;
                }
        }
-       return DIE_FIND_CB_SIBLING;
+       if (!lw->recursive)
+               /* Don't need to search recursively */
+               return DIE_FIND_CB_SIBLING;
+
+       if (addr) {
+               fname = dwarf_decl_file(in_die);
+               if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
+                       lw->retval = lw->callback(fname, lineno, addr, lw->data);
+                       if (lw->retval != 0)
+                               return DIE_FIND_CB_END;
+               }
+       }
+
+       /* Continue to search nested inlined function call-sites */
+       return DIE_FIND_CB_CONTINUE;
 }
 
 /* Walk on lines of blocks included in given DIE */
-static int __die_walk_funclines(Dwarf_Die *sp_die,
+static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
                                line_walk_callback_t callback, void *data)
 {
        struct __line_walk_param lw = {
+               .recursive = recursive,
                .callback = callback,
                .data = data,
                .retval = 0,
        };
        Dwarf_Die die_mem;
        Dwarf_Addr addr;
+       const char *fname;
        int lineno;
 
        /* Handle function declaration line */
-       lw.fname = dwarf_decl_file(sp_die);
-       if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
+       fname = dwarf_decl_file(sp_die);
+       if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
            dwarf_entrypc(sp_die, &addr) == 0) {
-               lw.retval = callback(lw.fname, lineno, addr, data);
+               lw.retval = callback(fname, lineno, addr, data);
                if (lw.retval != 0)
                        goto done;
        }
@@ -430,7 +606,7 @@ static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
 {
        struct __line_walk_param *lw = data;
 
-       lw->retval = __die_walk_funclines(sp_die, lw->callback, lw->data);
+       lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
        if (lw->retval != 0)
                return DWARF_CB_ABORT;
 
@@ -439,7 +615,7 @@ static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
 
 /**
  * die_walk_lines - Walk on lines inside given DIE
- * @rt_die: a root DIE (CU or subprogram)
+ * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
  * @callback: callback routine
  * @data: user data
  *
@@ -460,12 +636,12 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
        size_t nlines, i;
 
        /* Get the CU die */
-       if (dwarf_tag(rt_die) == DW_TAG_subprogram)
+       if (dwarf_tag(rt_die) != DW_TAG_compile_unit)
                cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
        else
                cu_die = rt_die;
        if (!cu_die) {
-               pr_debug2("Failed to get CU from subprogram\n");
+               pr_debug2("Failed to get CU from given DIE.\n");
                return -EINVAL;
        }
 
@@ -509,7 +685,11 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
         * subroutines. We have to check functions list or given function.
         */
        if (rt_die != cu_die)
-               ret = __die_walk_funclines(rt_die, callback, data);
+               /*
+                * Don't need walk functions recursively, because nested
+                * inlined functions don't have lines of the specified DIE.
+                */
+               ret = __die_walk_funclines(rt_die, false, callback, data);
        else {
                struct __line_walk_param param = {
                        .callback = callback,
index bc3b211..6ce1717 100644 (file)
@@ -34,12 +34,19 @@ extern const char *cu_get_comp_dir(Dwarf_Die *cu_die);
 extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
                            const char **fname, int *lineno);
 
+/* Walk on funcitons at given address */
+extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
+                       int (*callback)(Dwarf_Die *, void *), void *data);
+
 /* Compare diename and tname */
 extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
 
 /* Get callsite line number of inline-function instance */
 extern int die_get_call_lineno(Dwarf_Die *in_die);
 
+/* Get callsite file name of inlined function instance */
+extern const char *die_get_call_file(Dwarf_Die *in_die);
+
 /* Get type die */
 extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
 
@@ -73,6 +80,10 @@ extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
 extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
                                      Dwarf_Die *die_mem);
 
+/* Walk on the instances of given DIE */
+extern int die_walk_instances(Dwarf_Die *in_die,
+                             int (*callback)(Dwarf_Die *, void *), void *data);
+
 /* Walker on lines (Note: line number will not be sorted) */
 typedef int (* line_walk_callback_t) (const char *fname, int lineno,
                                      Dwarf_Addr addr, void *data);
index e03e7bc..c12bd47 100644 (file)
@@ -85,10 +85,19 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
        struct perf_evsel *evsel = perf_evsel__new(&attr, 0);
 
        if (evsel == NULL)
-               return -ENOMEM;
+               goto error;
+
+       /* use strdup() because free(evsel) assumes name is allocated */
+       evsel->name = strdup("cycles");
+       if (!evsel->name)
+               goto error_free;
 
        perf_evlist__add(evlist, evsel);
        return 0;
+error_free:
+       perf_evsel__delete(evsel);
+error:
+       return -ENOMEM;
 }
 
 void perf_evlist__disable(struct perf_evlist *evlist)
index d4f3101..b6c1ad1 100644 (file)
@@ -726,7 +726,16 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
                        return -1;
 
                bev.header = old_bev.header;
-               bev.pid    = 0;
+
+               /*
+                * As the pid is the missing value, we need to fill
+                * it properly. The header.misc value give us nice hint.
+                */
+               bev.pid = HOST_KERNEL_ID;
+               if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
+                   bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
+                       bev.pid = DEFAULT_GUEST_KERNEL_ID;
+
                memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
                __event_process_build_id(&bev, filename, session);
 
index 791f9dd..547628e 100644 (file)
@@ -5,7 +5,9 @@
 #define __always_inline        inline
 #endif
 #define __user
+#ifndef __attribute_const__
 #define __attribute_const__
+#endif
 
 #define __used         __attribute__((__unused__))
 
index 4ea7e19..928918b 100644 (file)
@@ -697,7 +697,11 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr)
                return EVT_FAILED;
        n = hex2u64(str + 1, &config);
        if (n > 0) {
-               *strp = str + n + 1;
+               const char *end = str + n + 1;
+               if (*end != '\0' && *end != ',' && *end != ':')
+                       return EVT_FAILED;
+
+               *strp = end;
                attr->type = PERF_TYPE_RAW;
                attr->config = config;
                return EVT_HANDLED;
@@ -1097,6 +1101,4 @@ void print_events(const char *event_glob)
        printf("\n");
 
        print_tracepoint_events(NULL, NULL);
-
-       exit(129);
 }
index 3e44a3e..555fc38 100644 (file)
@@ -612,12 +612,12 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
        return ret;
 }
 
-/* Find a variable in a subprogram die */
-static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
+/* Find a variable in a scope DIE */
+static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
 {
-       Dwarf_Die vr_die, *scopes;
+       Dwarf_Die vr_die;
        char buf[32], *ptr;
-       int ret, nscopes;
+       int ret = 0;
 
        if (!is_c_varname(pf->pvar->var)) {
                /* Copy raw parameters */
@@ -652,30 +652,16 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
        if (pf->tvar->name == NULL)
                return -ENOMEM;
 
-       pr_debug("Searching '%s' variable in context.\n",
-                pf->pvar->var);
+       pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
        /* Search child die for local variables and parameters. */
-       if (die_find_variable_at(sp_die, pf->pvar->var, pf->addr, &vr_die))
-               ret = convert_variable(&vr_die, pf);
-       else {
-               /* Search upper class */
-               nscopes = dwarf_getscopes_die(sp_die, &scopes);
-               while (nscopes-- > 1) {
-                       pr_debug("Searching variables in %s\n",
-                                dwarf_diename(&scopes[nscopes]));
-                       /* We should check this scope, so give dummy address */
-                       if (die_find_variable_at(&scopes[nscopes],
-                                                pf->pvar->var, 0,
-                                                &vr_die)) {
-                               ret = convert_variable(&vr_die, pf);
-                               goto found;
-                       }
-               }
-               if (scopes)
-                       free(scopes);
-               ret = -ENOENT;
+       if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
+               /* Search again in global variables */
+               if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
+                       ret = -ENOENT;
        }
-found:
+       if (ret == 0)
+               ret = convert_variable(&vr_die, pf);
+
        if (ret < 0)
                pr_warning("Failed to find '%s' in this function.\n",
                           pf->pvar->var);
@@ -718,26 +704,30 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
        return 0;
 }
 
-/* Call probe_finder callback with real subprogram DIE */
-static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
+/* Call probe_finder callback with scope DIE */
+static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
 {
-       Dwarf_Die die_mem;
        Dwarf_Attribute fb_attr;
        size_t nops;
        int ret;
 
-       /* If no real subprogram, find a real one */
-       if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
-               sp_die = die_find_realfunc(&pf->cu_die, pf->addr, &die_mem);
-               if (!sp_die) {
+       if (!sc_die) {
+               pr_err("Caller must pass a scope DIE. Program error.\n");
+               return -EINVAL;
+       }
+
+       /* If not a real subprogram, find a real one */
+       if (dwarf_tag(sc_die) != DW_TAG_subprogram) {
+               if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
                        pr_warning("Failed to find probe point in any "
                                   "functions.\n");
                        return -ENOENT;
                }
-       }
+       } else
+               memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
 
-       /* Get the frame base attribute/ops */
-       dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
+       /* Get the frame base attribute/ops from subprogram */
+       dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
        ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
        if (ret <= 0 || nops == 0) {
                pf->fb_ops = NULL;
@@ -755,7 +745,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
        }
 
        /* Call finder's callback handler */
-       ret = pf->callback(sp_die, pf);
+       ret = pf->callback(sc_die, pf);
 
        /* *pf->fb_ops will be cached in libdw. Don't free it. */
        pf->fb_ops = NULL;
@@ -763,17 +753,82 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
        return ret;
 }
 
+struct find_scope_param {
+       const char *function;
+       const char *file;
+       int line;
+       int diff;
+       Dwarf_Die *die_mem;
+       bool found;
+};
+
+static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
+{
+       struct find_scope_param *fsp = data;
+       const char *file;
+       int lno;
+
+       /* Skip if declared file name does not match */
+       if (fsp->file) {
+               file = dwarf_decl_file(fn_die);
+               if (!file || strcmp(fsp->file, file) != 0)
+                       return 0;
+       }
+       /* If the function name is given, that's what user expects */
+       if (fsp->function) {
+               if (die_compare_name(fn_die, fsp->function)) {
+                       memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
+                       fsp->found = true;
+                       return 1;
+               }
+       } else {
+               /* With the line number, find the nearest declared DIE */
+               dwarf_decl_line(fn_die, &lno);
+               if (lno < fsp->line && fsp->diff > fsp->line - lno) {
+                       /* Keep a candidate and continue */
+                       fsp->diff = fsp->line - lno;
+                       memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
+                       fsp->found = true;
+               }
+       }
+       return 0;
+}
+
+/* Find an appropriate scope fits to given conditions */
+static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
+{
+       struct find_scope_param fsp = {
+               .function = pf->pev->point.function,
+               .file = pf->fname,
+               .line = pf->lno,
+               .diff = INT_MAX,
+               .die_mem = die_mem,
+               .found = false,
+       };
+
+       cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp);
+
+       return fsp.found ? die_mem : NULL;
+}
+
 static int probe_point_line_walker(const char *fname, int lineno,
                                   Dwarf_Addr addr, void *data)
 {
        struct probe_finder *pf = data;
+       Dwarf_Die *sc_die, die_mem;
        int ret;
 
        if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
                return 0;
 
        pf->addr = addr;
-       ret = call_probe_finder(NULL, pf);
+       sc_die = find_best_scope(pf, &die_mem);
+       if (!sc_die) {
+               pr_warning("Failed to find scope of probe point.\n");
+               return -ENOENT;
+       }
+
+       ret = call_probe_finder(sc_die, pf);
 
        /* Continue if no error, because the line will be in inline function */
        return ret < 0 ? ret : 0;
@@ -827,6 +882,7 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
                                   Dwarf_Addr addr, void *data)
 {
        struct probe_finder *pf = data;
+       Dwarf_Die *sc_die, die_mem;
        int ret;
 
        if (!line_list__has_line(&pf->lcache, lineno) ||
@@ -836,7 +892,14 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
        pr_debug("Probe line found: line:%d addr:0x%llx\n",
                 lineno, (unsigned long long)addr);
        pf->addr = addr;
-       ret = call_probe_finder(NULL, pf);
+       pf->lno = lineno;
+       sc_die = find_best_scope(pf, &die_mem);
+       if (!sc_die) {
+               pr_warning("Failed to find scope of probe point.\n");
+               return -ENOENT;
+       }
+
+       ret = call_probe_finder(sc_die, pf);
 
        /*
         * Continue if no error, because the lazy pattern will match
@@ -861,42 +924,39 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
        return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
 }
 
-/* Callback parameter with return value */
-struct dwarf_callback_param {
-       void *data;
-       int retval;
-};
-
 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
 {
-       struct dwarf_callback_param *param = data;
-       struct probe_finder *pf = param->data;
+       struct probe_finder *pf = data;
        struct perf_probe_point *pp = &pf->pev->point;
        Dwarf_Addr addr;
+       int ret;
 
        if (pp->lazy_line)
-               param->retval = find_probe_point_lazy(in_die, pf);
+               ret = find_probe_point_lazy(in_die, pf);
        else {
                /* Get probe address */
                if (dwarf_entrypc(in_die, &addr) != 0) {
                        pr_warning("Failed to get entry address of %s.\n",
                                   dwarf_diename(in_die));
-                       param->retval = -ENOENT;
-                       return DWARF_CB_ABORT;
+                       return -ENOENT;
                }
                pf->addr = addr;
                pf->addr += pp->offset;
                pr_debug("found inline addr: 0x%jx\n",
                         (uintmax_t)pf->addr);
 
-               param->retval = call_probe_finder(in_die, pf);
-               if (param->retval < 0)
-                       return DWARF_CB_ABORT;
+               ret = call_probe_finder(in_die, pf);
        }
 
-       return DWARF_CB_OK;
+       return ret;
 }
 
+/* Callback parameter with return value for libdw */
+struct dwarf_callback_param {
+       void *data;
+       int retval;
+};
+
 /* Search function from function name */
 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 {
@@ -933,14 +993,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
                        /* TODO: Check the address in this function */
                        param->retval = call_probe_finder(sp_die, pf);
                }
-       } else {
-               struct dwarf_callback_param _param = {.data = (void *)pf,
-                                                     .retval = 0};
+       } else
                /* Inlined function: search instances */
-               dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
-                                           &_param);
-               param->retval = _param.retval;
-       }
+               param->retval = die_walk_instances(sp_die,
+                                       probe_point_inline_cb, (void *)pf);
 
        return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
 }
@@ -1060,7 +1116,7 @@ found:
 }
 
 /* Add a found probe point into trace event list */
-static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
+static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
 {
        struct trace_event_finder *tf =
                        container_of(pf, struct trace_event_finder, pf);
@@ -1075,8 +1131,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
        }
        tev = &tf->tevs[tf->ntevs++];
 
-       ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
-                                    &tev->point);
+       /* Trace point should be converted from subprogram DIE */
+       ret = convert_to_trace_point(&pf->sp_die, pf->addr,
+                                    pf->pev->point.retprobe, &tev->point);
        if (ret < 0)
                return ret;
 
@@ -1091,7 +1148,8 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
        for (i = 0; i < pf->pev->nargs; i++) {
                pf->pvar = &pf->pev->args[i];
                pf->tvar = &tev->args[i];
-               ret = find_variable(sp_die, pf);
+               /* Variable should be found from scope DIE */
+               ret = find_variable(sc_die, pf);
                if (ret != 0)
                        return ret;
        }
@@ -1159,13 +1217,13 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
 }
 
 /* Add a found vars into available variables list */
-static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
+static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
 {
        struct available_var_finder *af =
                        container_of(pf, struct available_var_finder, pf);
        struct variable_list *vl;
-       Dwarf_Die die_mem, *scopes = NULL;
-       int ret, nscopes;
+       Dwarf_Die die_mem;
+       int ret;
 
        /* Check number of tevs */
        if (af->nvls == af->max_vls) {
@@ -1174,8 +1232,9 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
        }
        vl = &af->vls[af->nvls++];
 
-       ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
-                                    &vl->point);
+       /* Trace point should be converted from subprogram DIE */
+       ret = convert_to_trace_point(&pf->sp_die, pf->addr,
+                                    pf->pev->point.retprobe, &vl->point);
        if (ret < 0)
                return ret;
 
@@ -1187,19 +1246,14 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
        if (vl->vars == NULL)
                return -ENOMEM;
        af->child = true;
-       die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem);
+       die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
 
        /* Find external variables */
        if (!af->externs)
                goto out;
        /* Don't need to search child DIE for externs. */
        af->child = false;
-       nscopes = dwarf_getscopes_die(sp_die, &scopes);
-       while (nscopes-- > 1)
-               die_find_child(&scopes[nscopes], collect_variables_cb,
-                              (void *)af, &die_mem);
-       if (scopes)
-               free(scopes);
+       die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
 
 out:
        if (strlist__empty(vl->vars)) {
@@ -1391,10 +1445,14 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
 
 static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
 {
-       struct dwarf_callback_param *param = data;
+       find_line_range_by_line(in_die, data);
 
-       param->retval = find_line_range_by_line(in_die, param->data);
-       return DWARF_CB_ABORT;  /* No need to find other instances */
+       /*
+        * We have to check all instances of inlined function, because
+        * some execution paths can be optimized out depends on the
+        * function argument of instances
+        */
+       return 0;
 }
 
 /* Search function from function name */
@@ -1422,15 +1480,10 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
                pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
                lr->start = lf->lno_s;
                lr->end = lf->lno_e;
-               if (dwarf_func_inline(sp_die)) {
-                       struct dwarf_callback_param _param;
-                       _param.data = (void *)lf;
-                       _param.retval = 0;
-                       dwarf_func_inline_instances(sp_die,
-                                                   line_range_inline_cb,
-                                                   &_param);
-                       param->retval = _param.retval;
-               } else
+               if (dwarf_func_inline(sp_die))
+                       param->retval = die_walk_instances(sp_die,
+                                               line_range_inline_cb, lf);
+               else
                        param->retval = find_line_range_by_line(sp_die, lf);
                return DWARF_CB_ABORT;
        }
index c478b42..1132c8f 100644 (file)
@@ -57,7 +57,7 @@ struct probe_finder {
        struct perf_probe_event *pev;           /* Target probe event */
 
        /* Callback when a probe point is found */
-       int (*callback)(Dwarf_Die *sp_die, struct probe_finder *pf);
+       int (*callback)(Dwarf_Die *sc_die, struct probe_finder *pf);
 
        /* For function searching */
        int                     lno;            /* Line number */
index a8b5371..469c026 100644 (file)
@@ -1506,7 +1506,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
        if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
                struct stat st;
 
-               if (stat(dso->name, &st) < 0)
+               if (lstat(dso->name, &st) < 0)
                        return -1;
 
                if (st.st_uid && (st.st_uid != geteuid())) {
@@ -2181,27 +2181,22 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
        return ret;
 }
 
-struct dso *dso__new_kernel(const char *name)
+static struct dso*
+dso__kernel_findnew(struct machine *machine, const char *name,
+                   const char *short_name, int dso_type)
 {
-       struct dso *dso = dso__new(name ?: "[kernel.kallsyms]");
-
-       if (dso != NULL) {
-               dso__set_short_name(dso, "[kernel]");
-               dso->kernel = DSO_TYPE_KERNEL;
-       }
-
-       return dso;
-}
+       /*
+        * The kernel dso could be created by build_id processing.
+        */
+       struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
 
-static struct dso *dso__new_guest_kernel(struct machine *machine,
-                                       const char *name)
-{
-       char bf[PATH_MAX];
-       struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf,
-                                                             sizeof(bf)));
+       /*
+        * We need to run this in all cases, since during the build_id
+        * processing we had no idea this was the kernel dso.
+        */
        if (dso != NULL) {
-               dso__set_short_name(dso, "[guest.kernel]");
-               dso->kernel = DSO_TYPE_GUEST_KERNEL;
+               dso__set_short_name(dso, short_name);
+               dso->kernel = dso_type;
        }
 
        return dso;
@@ -2219,24 +2214,36 @@ void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
                dso->has_build_id = true;
 }
 
-static struct dso *machine__create_kernel(struct machine *machine)
+static struct dso *machine__get_kernel(struct machine *machine)
 {
        const char *vmlinux_name = NULL;
        struct dso *kernel;
 
        if (machine__is_host(machine)) {
                vmlinux_name = symbol_conf.vmlinux_name;
-               kernel = dso__new_kernel(vmlinux_name);
+               if (!vmlinux_name)
+                       vmlinux_name = "[kernel.kallsyms]";
+
+               kernel = dso__kernel_findnew(machine, vmlinux_name,
+                                            "[kernel]",
+                                            DSO_TYPE_KERNEL);
        } else {
+               char bf[PATH_MAX];
+
                if (machine__is_default_guest(machine))
                        vmlinux_name = symbol_conf.default_guest_vmlinux_name;
-               kernel = dso__new_guest_kernel(machine, vmlinux_name);
+               if (!vmlinux_name)
+                       vmlinux_name = machine__mmap_name(machine, bf,
+                                                         sizeof(bf));
+
+               kernel = dso__kernel_findnew(machine, vmlinux_name,
+                                            "[guest.kernel]",
+                                            DSO_TYPE_GUEST_KERNEL);
        }
 
-       if (kernel != NULL) {
+       if (kernel != NULL && (!kernel->has_build_id))
                dso__read_running_kernel_build_id(kernel, machine);
-               dsos__add(&machine->kernel_dsos, kernel);
-       }
+
        return kernel;
 }
 
@@ -2340,7 +2347,7 @@ void machine__destroy_kernel_maps(struct machine *machine)
 
 int machine__create_kernel_maps(struct machine *machine)
 {
-       struct dso *kernel = machine__create_kernel(machine);
+       struct dso *kernel = machine__get_kernel(machine);
 
        if (kernel == NULL ||
            __machine__create_kernel_maps(machine, kernel) < 0)
index 325ee36..4f377d9 100644 (file)
@@ -155,7 +155,6 @@ struct dso {
 };
 
 struct dso *dso__new(const char *name);
-struct dso *dso__new_kernel(const char *name);
 void dso__delete(struct dso *dso);
 
 int dso__name_len(const struct dso *dso);
index 5a06538..88403cf 100644 (file)
@@ -208,6 +208,5 @@ int perf_top__tui_browser(struct perf_top *top)
                },
        };
 
-       ui_helpline__push("Press <- or ESC to exit");
        return perf_top_browser__run(&browser);
 }
index 94c2cf0..e8a03ac 100644 (file)
@@ -24,7 +24,7 @@
 
 # Set the following to `true' to make a unstripped, unoptimized
 # binary. Leave this set to `false' for production use.
-DEBUG ?=       false
+DEBUG ?=       true
 
 # make the build silent. Set this to something else to make it noisy again.
 V ?=           false
@@ -35,7 +35,7 @@ NLS ?=                true
 
 # Set the following to 'true' to build/install the
 # cpufreq-bench benchmarking tool
-CPUFRQ_BENCH ?= true
+CPUFREQ_BENCH ?= true
 
 # Prefix to the directories we're installing to
 DESTDIR ?=
@@ -137,9 +137,10 @@ CFLAGS +=  -pipe
 ifeq ($(strip $(NLS)),true)
        INSTALL_NLS += install-gmo
        COMPILE_NLS += create-gmo
+       CFLAGS += -DNLS
 endif
 
-ifeq ($(strip $(CPUFRQ_BENCH)),true)
+ifeq ($(strip $(CPUFREQ_BENCH)),true)
        INSTALL_BENCH += install-bench
        COMPILE_BENCH += compile-bench
 endif
index dbf1399..3326217 100644 (file)
@@ -1,10 +1,10 @@
 default: all
 
-centrino-decode: centrino-decode.c
-       $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c
+centrino-decode: ../i386/centrino-decode.c
+       $(CC) $(CFLAGS) -o $@ $<
 
-powernow-k8-decode: powernow-k8-decode.c
-       $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c
+powernow-k8-decode: ../i386/powernow-k8-decode.c
+       $(CC) $(CFLAGS) -o $@ $<
 
 all: centrino-decode powernow-k8-decode
 
diff --git a/tools/power/cpupower/debug/x86_64/centrino-decode.c b/tools/power/cpupower/debug/x86_64/centrino-decode.c
deleted file mode 120000 (symlink)
index 26fb3f1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../i386/centrino-decode.c
\ No newline at end of file
diff --git a/tools/power/cpupower/debug/x86_64/powernow-k8-decode.c b/tools/power/cpupower/debug/x86_64/powernow-k8-decode.c
deleted file mode 120000 (symlink)
index eb30c79..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../i386/powernow-k8-decode.c
\ No newline at end of file
index 3194811..bb60a8d 100644 (file)
@@ -1,10 +1,10 @@
-.TH "cpufreq-info" "1" "0.1" "Mattia Dongili" ""
+.TH "cpupower-frequency-info" "1" "0.1" "Mattia Dongili" ""
 .SH "NAME"
 .LP 
-cpufreq\-info \- Utility to retrieve cpufreq kernel information
+cpupower frequency\-info \- Utility to retrieve cpufreq kernel information
 .SH "SYNTAX"
 .LP 
-cpufreq\-info [\fIoptions\fP]
+cpupower [ \-c cpulist ] frequency\-info [\fIoptions\fP]
 .SH "DESCRIPTION"
 .LP 
 A small tool which prints out cpufreq information helpful to developers and interested users.
index 26e3e13..685f469 100644 (file)
@@ -1,13 +1,13 @@
-.TH "cpufreq-set" "1" "0.1" "Mattia Dongili" ""
+.TH "cpupower-freqency-set" "1" "0.1" "Mattia Dongili" ""
 .SH "NAME"
 .LP 
-cpufreq\-set \- A small tool which allows to modify cpufreq settings.
+cpupower frequency\-set \- A small tool which allows to modify cpufreq settings.
 .SH "SYNTAX"
 .LP 
-cpufreq\-set [\fIoptions\fP]
+cpupower [ \-c cpu ] frequency\-set [\fIoptions\fP]
 .SH "DESCRIPTION"
 .LP 
-cpufreq\-set allows you to modify cpufreq settings without having to type e.g. "/sys/devices/system/cpu/cpu0/cpufreq/scaling_set_speed" all the time.
+cpupower frequency\-set allows you to modify cpufreq settings without having to type e.g. "/sys/devices/system/cpu/cpu0/cpufreq/scaling_set_speed" all the time.
 .SH "OPTIONS"
 .LP 
 .TP 
index 78c20fe..baf741d 100644 (file)
@@ -3,7 +3,7 @@
 cpupower \- Shows and sets processor power related values
 .SH SYNOPSIS
 .ft B
-.B cpupower [ \-c cpulist ] subcommand [ARGS]
+.B cpupower [ \-c cpulist ] <command> [ARGS]
 
 .B cpupower \-v|\-\-version
 
@@ -13,24 +13,24 @@ cpupower \- Shows and sets processor power related values
 \fBcpupower \fP is a collection of tools to examine and tune power saving
 related features of your processor.
 
-The manpages of the subcommands (cpupower\-<subcommand>(1)) provide detailed
+The manpages of the commands (cpupower\-<command>(1)) provide detailed
 descriptions of supported features. Run \fBcpupower help\fP to get an overview
-of supported subcommands.
+of supported commands.
 
 .SH Options
 .PP
 \-\-help, \-h
 .RS 4
-Shows supported subcommands and general usage.
+Shows supported commands and general usage.
 .RE
 .PP
 \-\-cpu cpulist,  \-c cpulist
 .RS 4
 Only show or set values for specific cores.
-This option is not supported by all subcommands, details can be found in the
-manpages of the subcommands.
+This option is not supported by all commands, details can be found in the
+manpages of the commands.
 
-Some subcommands access all cores (typically the *\-set commands), some only
+Some commands access all cores (typically the *\-set commands), some only
 the first core (typically the *\-info commands) by default.
 
 The syntax for <cpulist> is based on how the kernel exports CPU bitmasks via
index c870ffb..c10496f 100644 (file)
@@ -8,11 +8,4 @@ extern int cmd_freq_info(int argc, const char **argv);
 extern int cmd_idle_info(int argc, const char **argv);
 extern int cmd_monitor(int argc, const char **argv);
 
-extern void set_help(void);
-extern void info_help(void);
-extern void freq_set_help(void);
-extern void freq_info_help(void);
-extern void idle_info_help(void);
-extern void monitor_help(void);
-
 #endif
index 5a1d25f..28953c9 100644 (file)
@@ -510,37 +510,6 @@ static int get_latency(unsigned int cpu, unsigned int human)
        return 0;
 }
 
-void freq_info_help(void)
-{
-       printf(_("Usage: cpupower freqinfo [options]\n"));
-       printf(_("Options:\n"));
-       printf(_("  -e, --debug          Prints out debug information [default]\n"));
-       printf(_("  -f, --freq           Get frequency the CPU currently runs at, according\n"
-              "                       to the cpufreq core *\n"));
-       printf(_("  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
-              "                       it from hardware (only available to root) *\n"));
-       printf(_("  -l, --hwlimits       Determine the minimum and maximum CPU frequency allowed *\n"));
-       printf(_("  -d, --driver         Determines the used cpufreq kernel driver *\n"));
-       printf(_("  -p, --policy         Gets the currently used cpufreq policy *\n"));
-       printf(_("  -g, --governors      Determines available cpufreq governors *\n"));
-       printf(_("  -r, --related-cpus   Determines which CPUs run at the same hardware frequency *\n"));
-       printf(_("  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
-                       "                       coordinated by software *\n"));
-       printf(_("  -s, --stats          Shows cpufreq statistics if available\n"));
-       printf(_("  -y, --latency        Determines the maximum latency on CPU frequency changes *\n"));
-       printf(_("  -b, --boost          Checks for turbo or boost modes  *\n"));
-       printf(_("  -o, --proc           Prints out information like provided by the /proc/cpufreq\n"
-              "                       interface in 2.4. and early 2.6. kernels\n"));
-       printf(_("  -m, --human          human-readable output for the -f, -w, -s and -y parameters\n"));
-       printf(_("  -h, --help           Prints out this screen\n"));
-
-       printf("\n");
-       printf(_("If no argument is given, full output about\n"
-              "cpufreq is printed which is useful e.g. for reporting bugs.\n\n"));
-       printf(_("By default info of CPU 0 is shown which can be overridden\n"
-                "with the cpupower --cpu main command option.\n"));
-}
-
 static struct option info_opts[] = {
        { .name = "debug",      .has_arg = no_argument,         .flag = NULL,   .val = 'e'},
        { .name = "boost",      .has_arg = no_argument,         .flag = NULL,   .val = 'b'},
@@ -556,7 +525,6 @@ static struct option info_opts[] = {
        { .name = "latency",    .has_arg = no_argument,         .flag = NULL,   .val = 'y'},
        { .name = "proc",       .has_arg = no_argument,         .flag = NULL,   .val = 'o'},
        { .name = "human",      .has_arg = no_argument,         .flag = NULL,   .val = 'm'},
-       { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
        { },
 };
 
@@ -570,16 +538,12 @@ int cmd_freq_info(int argc, char **argv)
        int output_param = 0;
 
        do {
-               ret = getopt_long(argc, argv, "hoefwldpgrasmyb", info_opts, NULL);
+               ret = getopt_long(argc, argv, "oefwldpgrasmyb", info_opts, NULL);
                switch (ret) {
                case '?':
                        output_param = '?';
                        cont = 0;
                        break;
-               case 'h':
-                       output_param = 'h';
-                       cont = 0;
-                       break;
                case -1:
                        cont = 0;
                        break;
@@ -642,11 +606,7 @@ int cmd_freq_info(int argc, char **argv)
                return -EINVAL;
        case '?':
                printf(_("invalid or unknown argument\n"));
-               freq_info_help();
                return -EINVAL;
-       case 'h':
-               freq_info_help();
-               return EXIT_SUCCESS;
        case 'o':
                proc_cpufreq_output();
                return EXIT_SUCCESS;
index 5f78362..dd1539e 100644 (file)
 
 #define NORM_FREQ_LEN 32
 
-void freq_set_help(void)
-{
-       printf(_("Usage: cpupower frequency-set [options]\n"));
-       printf(_("Options:\n"));
-       printf(_("  -d FREQ, --min FREQ      new minimum CPU frequency the governor may select\n"));
-       printf(_("  -u FREQ, --max FREQ      new maximum CPU frequency the governor may select\n"));
-       printf(_("  -g GOV, --governor GOV   new cpufreq governor\n"));
-       printf(_("  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
-              "                           governor to be available and loaded\n"));
-       printf(_("  -r, --related            Switches all hardware-related CPUs\n"));
-       printf(_("  -h, --help               Prints out this screen\n"));
-       printf("\n");
-       printf(_("Notes:\n"
-              "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"));
-       printf(_("2. The -f FREQ, --freq FREQ parameter cannot be combined with any other parameter\n"
-              "   except the -c CPU, --cpu CPU parameter\n"
-              "3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
-              "   by postfixing the value with the wanted unit name, without any space\n"
-              "   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"));
-
-}
-
 static struct option set_opts[] = {
        { .name = "min",        .has_arg = required_argument,   .flag = NULL,   .val = 'd'},
        { .name = "max",        .has_arg = required_argument,   .flag = NULL,   .val = 'u'},
        { .name = "governor",   .has_arg = required_argument,   .flag = NULL,   .val = 'g'},
        { .name = "freq",       .has_arg = required_argument,   .flag = NULL,   .val = 'f'},
-       { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
        { .name = "related",    .has_arg = no_argument,         .flag = NULL,   .val='r'},
        { },
 };
@@ -80,7 +57,6 @@ const struct freq_units def_units[] = {
 static void print_unknown_arg(void)
 {
        printf(_("invalid or unknown argument\n"));
-       freq_set_help();
 }
 
 static unsigned long string_to_frequency(const char *str)
@@ -231,14 +207,11 @@ int cmd_freq_set(int argc, char **argv)
 
        /* parameter parsing */
        do {
-               ret = getopt_long(argc, argv, "d:u:g:f:hr", set_opts, NULL);
+               ret = getopt_long(argc, argv, "d:u:g:f:r", set_opts, NULL);
                switch (ret) {
                case '?':
                        print_unknown_arg();
                        return -EINVAL;
-               case 'h':
-                       freq_set_help();
-                       return 0;
                case -1:
                        cont = 0;
                        break;
index 70da357..b028267 100644 (file)
@@ -139,30 +139,14 @@ static void proc_cpuidle_cpu_output(unsigned int cpu)
        }
 }
 
-/* --freq / -f */
-
-void idle_info_help(void)
-{
-       printf(_ ("Usage: cpupower idleinfo [options]\n"));
-       printf(_ ("Options:\n"));
-       printf(_ ("  -s, --silent         Only show general C-state information\n"));
-       printf(_ ("  -o, --proc           Prints out information like provided by the /proc/acpi/processor/*/power\n"
-              "                       interface in older kernels\n"));
-       printf(_ ("  -h, --help           Prints out this screen\n"));
-
-       printf("\n");
-}
-
 static struct option info_opts[] = {
        { .name = "silent",     .has_arg = no_argument, .flag = NULL,   .val = 's'},
        { .name = "proc",       .has_arg = no_argument, .flag = NULL,   .val = 'o'},
-       { .name = "help",       .has_arg = no_argument, .flag = NULL,   .val = 'h'},
        { },
 };
 
 static inline void cpuidle_exit(int fail)
 {
-       idle_info_help();
        exit(EXIT_FAILURE);
 }
 
@@ -174,7 +158,7 @@ int cmd_idle_info(int argc, char **argv)
        unsigned int cpu = 0;
 
        do {
-               ret = getopt_long(argc, argv, "hos", info_opts, NULL);
+               ret = getopt_long(argc, argv, "os", info_opts, NULL);
                if (ret == -1)
                        break;
                switch (ret) {
@@ -182,10 +166,6 @@ int cmd_idle_info(int argc, char **argv)
                        output_param = '?';
                        cont = 0;
                        break;
-               case 'h':
-                       output_param = 'h';
-                       cont = 0;
-                       break;
                case 's':
                        verbose = 0;
                        break;
@@ -211,8 +191,6 @@ int cmd_idle_info(int argc, char **argv)
        case '?':
                printf(_("invalid or unknown argument\n"));
                cpuidle_exit(EXIT_FAILURE);
-       case 'h':
-               cpuidle_exit(EXIT_SUCCESS);
        }
 
        /* Default is: show output of CPU 0 only */
index 85253cb..3f68632 100644 (file)
 #include "helpers/helpers.h"
 #include "helpers/sysfs.h"
 
-void info_help(void)
-{
-       printf(_("Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"));
-       printf(_("Options:\n"));
-       printf(_("  -b, --perf-bias    Gets CPU's power vs performance policy on some\n"
-              "                           Intel models [0-15], see manpage for details\n"));
-       printf(_("  -m, --sched-mc     Gets the kernel's multi core scheduler policy.\n"));
-       printf(_("  -s, --sched-smt    Gets the kernel's thread sibling scheduler policy.\n"));
-       printf(_("  -h, --help               Prints out this screen\n"));
-       printf(_("\nPassing no option will show all info, by default only on core 0\n"));
-       printf("\n");
-}
-
 static struct option set_opts[] = {
        { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
        { .name = "sched-mc",   .has_arg = optional_argument,   .flag = NULL,   .val = 'm'},
        { .name = "sched-smt",  .has_arg = optional_argument,   .flag = NULL,   .val = 's'},
-       { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
        { },
 };
 
 static void print_wrong_arg_exit(void)
 {
        printf(_("invalid or unknown argument\n"));
-       info_help();
        exit(EXIT_FAILURE);
 }
 
@@ -64,11 +49,8 @@ int cmd_info(int argc, char **argv)
        textdomain(PACKAGE);
 
        /* parameter parsing */
-       while ((ret = getopt_long(argc, argv, "msbh", set_opts, NULL)) != -1) {
+       while ((ret = getopt_long(argc, argv, "msb", set_opts, NULL)) != -1) {
                switch (ret) {
-               case 'h':
-                       info_help();
-                       return 0;
                case 'b':
                        if (params.perf_bias)
                                print_wrong_arg_exit();
index bc1b391..dc4de37 100644 (file)
 #include "helpers/sysfs.h"
 #include "helpers/bitmask.h"
 
-void set_help(void)
-{
-       printf(_("Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"));
-       printf(_("Options:\n"));
-       printf(_("  -b, --perf-bias [VAL]    Sets CPU's power vs performance policy on some\n"
-              "                           Intel models [0-15], see manpage for details\n"));
-       printf(_("  -m, --sched-mc  [VAL]    Sets the kernel's multi core scheduler policy.\n"));
-       printf(_("  -s, --sched-smt [VAL]    Sets the kernel's thread sibling scheduler policy.\n"));
-       printf(_("  -h, --help               Prints out this screen\n"));
-       printf("\n");
-}
-
 static struct option set_opts[] = {
        { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
        { .name = "sched-mc",   .has_arg = optional_argument,   .flag = NULL,   .val = 'm'},
        { .name = "sched-smt",  .has_arg = optional_argument,   .flag = NULL,   .val = 's'},
-       { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
        { },
 };
 
 static void print_wrong_arg_exit(void)
 {
        printf(_("invalid or unknown argument\n"));
-       set_help();
        exit(EXIT_FAILURE);
 }
 
@@ -66,12 +52,9 @@ int cmd_set(int argc, char **argv)
 
        params.params = 0;
        /* parameter parsing */
-       while ((ret = getopt_long(argc, argv, "m:s:b:h",
+       while ((ret = getopt_long(argc, argv, "m:s:b:",
                                                set_opts, NULL)) != -1) {
                switch (ret) {
-               case 'h':
-                       set_help();
-                       return 0;
                case 'b':
                        if (params.perf_bias)
                                print_wrong_arg_exit();
@@ -110,10 +93,8 @@ int cmd_set(int argc, char **argv)
                }
        };
 
-       if (!params.params) {
-               set_help();
-               return -EINVAL;
-       }
+       if (!params.params)
+               print_wrong_arg_exit();
 
        if (params.sched_mc) {
                ret = sysfs_set_sched("mc", sched_mc);
index 5844ae0..52bee59 100644 (file)
@@ -11,6 +11,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include "builtin.h"
 #include "helpers/helpers.h"
 struct cmd_struct {
        const char *cmd;
        int (*main)(int, const char **);
-       void (*usage)(void);
        int needs_root;
 };
 
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
 
-int cmd_help(int argc, const char **argv);
+static int cmd_help(int argc, const char **argv);
 
 /* Global cpu_info object available for all binaries
  * Info only retrieved from CPU 0
@@ -44,55 +44,66 @@ int be_verbose;
 static void print_help(void);
 
 static struct cmd_struct commands[] = {
-       { "frequency-info",     cmd_freq_info,  freq_info_help, 0       },
-       { "frequency-set",      cmd_freq_set,   freq_set_help,  1       },
-       { "idle-info",          cmd_idle_info,  idle_info_help, 0       },
-       { "set",                cmd_set,        set_help,       1       },
-       { "info",               cmd_info,       info_help,      0       },
-       { "monitor",            cmd_monitor,    monitor_help,   0       },
-       { "help",               cmd_help,       print_help,     0       },
-       /*      { "bench",      cmd_bench,      NULL,           1       }, */
+       { "frequency-info",     cmd_freq_info,  0       },
+       { "frequency-set",      cmd_freq_set,   1       },
+       { "idle-info",          cmd_idle_info,  0       },
+       { "set",                cmd_set,        1       },
+       { "info",               cmd_info,       0       },
+       { "monitor",            cmd_monitor,    0       },
+       { "help",               cmd_help,       0       },
+       /*      { "bench",      cmd_bench,      1       }, */
 };
 
-int cmd_help(int argc, const char **argv)
-{
-       unsigned int i;
-
-       if (argc > 1) {
-               for (i = 0; i < ARRAY_SIZE(commands); i++) {
-                       struct cmd_struct *p = commands + i;
-                       if (strcmp(p->cmd, argv[1]))
-                               continue;
-                       if (p->usage) {
-                               p->usage();
-                               return EXIT_SUCCESS;
-                       }
-               }
-       }
-       print_help();
-       if (argc == 1)
-               return EXIT_SUCCESS; /* cpupower help */
-       return EXIT_FAILURE;
-}
-
 static void print_help(void)
 {
        unsigned int i;
 
 #ifdef DEBUG
-       printf(_("cpupower [ -d ][ -c cpulist ] subcommand [ARGS]\n"));
-       printf(_("  -d, --debug      May increase output (stderr) on some subcommands\n"));
+       printf(_("Usage:\tcpupower [-d|--debug] [-c|--cpu cpulist ] <command> [<args>]\n"));
 #else
-       printf(_("cpupower [ -c cpulist ] subcommand [ARGS]\n"));
+       printf(_("Usage:\tcpupower [-c|--cpu cpulist ] <command> [<args>]\n"));
 #endif
-       printf(_("cpupower --version\n"));
-       printf(_("Supported subcommands are:\n"));
+       printf(_("Supported commands are:\n"));
        for (i = 0; i < ARRAY_SIZE(commands); i++)
                printf("\t%s\n", commands[i].cmd);
-       printf(_("\nSome subcommands can make use of the -c cpulist option.\n"));
-       printf(_("Look at the general cpupower manpage how to use it\n"));
-       printf(_("and read up the subcommand's manpage whether it is supported.\n"));
-       printf(_("\nUse cpupower help subcommand for getting help for above subcommands.\n"));
+       printf(_("\nNot all commands can make use of the -c cpulist option.\n"));
+       printf(_("\nUse 'cpupower help <command>' for getting help for above commands.\n"));
+}
+
+static int print_man_page(const char *subpage)
+{
+       int len;
+       char *page;
+
+       len = 10; /* enough for "cpupower-" */
+       if (subpage != NULL)
+               len += strlen(subpage);
+
+       page = malloc(len);
+       if (!page)
+               return -ENOMEM;
+
+       sprintf(page, "cpupower");
+       if ((subpage != NULL) && strcmp(subpage, "help")) {
+               strcat(page, "-");
+               strcat(page, subpage);
+       }
+
+       execlp("man", "man", page, NULL);
+
+       /* should not be reached */
+       return -EINVAL;
+}
+
+static int cmd_help(int argc, const char **argv)
+{
+       if (argc > 1) {
+               print_man_page(argv[1]); /* exits within execlp() */
+               return EXIT_FAILURE;
+       }
+
+       print_help();
+       return EXIT_SUCCESS;
 }
 
 static void print_version(void)
index 592ee36..2747e73 100644 (file)
 #include "helpers/bitmask.h"
 
 /* Internationalization ****************************/
+#ifdef NLS
+
 #define _(String) gettext(String)
 #ifndef gettext_noop
 #define gettext_noop(String) String
 #endif
 #define N_(String) gettext_noop(String)
+
+#else /* !NLS */
+
+#define _(String) String
+#define N_(String) String
+
+#endif
 /* Internationalization ****************************/
 
 extern int run_as_root;
@@ -96,6 +105,9 @@ struct cpupower_topology {
                int pkg;
                int core;
                int cpu;
+
+               /* flags */
+               unsigned int is_online:1;
        } *core_info;
 };
 
index 55e2466..c634302 100644 (file)
@@ -56,6 +56,56 @@ static unsigned int sysfs_write_file(const char *path,
        return (unsigned int) numwrite;
 }
 
+/*
+ * Detect whether a CPU is online
+ *
+ * Returns:
+ *     1 -> if CPU is online
+ *     0 -> if CPU is offline
+ *     negative errno values in error case
+ */
+int sysfs_is_cpu_online(unsigned int cpu)
+{
+       char path[SYSFS_PATH_MAX];
+       int fd;
+       ssize_t numread;
+       unsigned long long value;
+       char linebuf[MAX_LINE_LEN];
+       char *endp;
+       struct stat statbuf;
+
+       snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
+
+       if (stat(path, &statbuf) != 0)
+               return 0;
+
+       /*
+        * kernel without CONFIG_HOTPLUG_CPU
+        * -> cpuX directory exists, but not cpuX/online file
+        */
+       snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
+       if (stat(path, &statbuf) != 0)
+               return 1;
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return -errno;
+
+       numread = read(fd, linebuf, MAX_LINE_LEN - 1);
+       if (numread < 1) {
+               close(fd);
+               return -EIO;
+       }
+       linebuf[numread] = '\0';
+       close(fd);
+
+       value = strtoull(linebuf, &endp, 0);
+       if (value > 1 || value < 0)
+               return -EINVAL;
+
+       return value;
+}
+
 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
 
 /*
index f9373e0..8cb797b 100644 (file)
@@ -7,6 +7,8 @@
 
 extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
 
+extern int sysfs_is_cpu_online(unsigned int cpu);
+
 extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
                                                unsigned int idlestate);
 extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
index 385ee5c..4eae2c4 100644 (file)
@@ -41,6 +41,8 @@ struct cpuid_core_info {
        unsigned int pkg;
        unsigned int thread;
        unsigned int cpu;
+       /* flags */
+       unsigned int is_online:1;
 };
 
 static int __compare(const void *t1, const void *t2)
@@ -78,6 +80,8 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
                return -ENOMEM;
        cpu_top->pkgs = cpu_top->cores = 0;
        for (cpu = 0; cpu < cpus; cpu++) {
+               cpu_top->core_info[cpu].cpu = cpu;
+               cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
                cpu_top->core_info[cpu].pkg =
                        sysfs_topology_read_file(cpu, "physical_package_id");
                if ((int)cpu_top->core_info[cpu].pkg != -1 &&
@@ -85,7 +89,6 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
                        cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
                cpu_top->core_info[cpu].core =
                        sysfs_topology_read_file(cpu, "core_id");
-               cpu_top->core_info[cpu].cpu = cpu;
        }
        cpu_top->pkgs++;
 
index d048b96..bcd22a1 100644 (file)
@@ -134,7 +134,7 @@ static struct cpuidle_monitor *cpuidle_register(void)
        /* Assume idle state count is the same for all CPUs */
        cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0);
 
-       if (cpuidle_sysfs_monitor.hw_states_num == 0)
+       if (cpuidle_sysfs_monitor.hw_states_num <= 0)
                return NULL;
 
        for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
index ba4bf06..0d6571e 100644 (file)
@@ -43,6 +43,12 @@ static struct cpupower_topology cpu_top;
 /* ToDo: Document this in the manpage */
 static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', };
 
+static void print_wrong_arg_exit(void)
+{
+       printf(_("invalid or unknown argument\n"));
+       exit(EXIT_FAILURE);
+}
+
 long long timespec_diff_us(struct timespec start, struct timespec end)
 {
        struct timespec temp;
@@ -56,21 +62,6 @@ long long timespec_diff_us(struct timespec start, struct timespec end)
        return (temp.tv_sec * 1000000) + (temp.tv_nsec / 1000);
 }
 
-void monitor_help(void)
-{
-       printf(_("cpupower monitor: [-m <mon1>,[<mon2>],.. ] command\n"));
-       printf(_("cpupower monitor: [-m <mon1>,[<mon2>],.. ] [ -i interval_sec ]\n"));
-       printf(_("cpupower monitor: -l\n"));
-       printf(_("\t command: pass an arbitrary command to measure specific workload\n"));
-       printf(_("\t -i: time intervall to measure for in seconds (default 1)\n"));
-       printf(_("\t -l: list available CPU sleep monitors (for use with -m)\n"));
-       printf(_("\t -m: show specific CPU sleep monitors only (in same order)\n"));
-       printf(_("\t -h: print this help\n"));
-       printf("\n");
-       printf(_("only one of: -l, -m are allowed\nIf none of them is passed,"));
-       printf(_(" all supported monitors are shown\n"));
-}
-
 void print_n_spaces(int n)
 {
        int x;
@@ -149,6 +140,10 @@ void print_results(int topology_depth, int cpu)
        unsigned long long result;
        cstate_t s;
 
+       /* Be careful CPUs may got resorted for pkg value do not just use cpu */
+       if (!bitmask_isbitset(cpus_chosen, cpu_top.core_info[cpu].cpu))
+               return;
+
        if (topology_depth > 2)
                printf("%4d|", cpu_top.core_info[cpu].pkg);
        if (topology_depth > 1)
@@ -190,9 +185,13 @@ void print_results(int topology_depth, int cpu)
                        }
                }
        }
-       /* cpu offline */
-       if (cpu_top.core_info[cpu].pkg == -1 ||
-           cpu_top.core_info[cpu].core == -1) {
+       /*
+        * The monitor could still provide useful data, for example
+        * AMD HW counters partly sit in PCI config space.
+        * It's up to the monitor plug-in to check .is_online, this one
+        * is just for additional info.
+        */
+       if (!cpu_top.core_info[cpu].is_online) {
                printf(_(" *is offline\n"));
                return;
        } else
@@ -238,7 +237,6 @@ static void parse_monitor_param(char *param)
        if (hits == 0) {
                printf(_("No matching monitor found in %s, "
                         "try -l option\n"), param);
-               monitor_help();
                exit(EXIT_FAILURE);
        }
        /* Override detected/registerd monitors array with requested one */
@@ -335,37 +333,27 @@ static void cmdline(int argc, char *argv[])
        int opt;
        progname = basename(argv[0]);
 
-       while ((opt = getopt(argc, argv, "+hli:m:")) != -1) {
+       while ((opt = getopt(argc, argv, "+li:m:")) != -1) {
                switch (opt) {
-               case 'h':
-                       monitor_help();
-                       exit(EXIT_SUCCESS);
                case 'l':
-                       if (mode) {
-                               monitor_help();
-                               exit(EXIT_FAILURE);
-                       }
+                       if (mode)
+                               print_wrong_arg_exit();
                        mode = list;
                        break;
                case 'i':
                        /* only allow -i with -m or no option */
-                       if (mode && mode != show) {
-                               monitor_help();
-                               exit(EXIT_FAILURE);
-                       }
+                       if (mode && mode != show)
+                               print_wrong_arg_exit();
                        interval = atoi(optarg);
                        break;
                case 'm':
-                       if (mode) {
-                               monitor_help();
-                               exit(EXIT_FAILURE);
-                       }
+                       if (mode)
+                               print_wrong_arg_exit();
                        mode = show;
                        show_monitors_param = optarg;
                        break;
                default:
-                       monitor_help();
-                       exit(EXIT_FAILURE);
+                       print_wrong_arg_exit();
                }
        }
        if (!mode)
@@ -385,6 +373,10 @@ int cmd_monitor(int argc, char **argv)
                return EXIT_FAILURE;
        }
 
+       /* Default is: monitor all CPUs */
+       if (bitmask_isallclear(cpus_chosen))
+               bitmask_setall(cpus_chosen);
+
        dprint("System has up to %d CPU cores\n", cpu_count);
 
        for (num = 0; all_monitors[num]; num++) {
index 63ca87a..5650ab5 100644 (file)
 
 #define MSR_TSC        0x10
 
+#define MSR_AMD_HWCR 0xc0010015
+
 enum mperf_id { C0 = 0, Cx, AVG_FREQ, MPERF_CSTATE_COUNT };
 
 static int mperf_get_count_percent(unsigned int self_id, double *percent,
                                   unsigned int cpu);
 static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
                                unsigned int cpu);
+static struct timespec time_start, time_end;
 
 static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
        {
@@ -54,19 +57,33 @@ static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
        },
 };
 
+enum MAX_FREQ_MODE { MAX_FREQ_SYSFS, MAX_FREQ_TSC_REF };
+static int max_freq_mode;
+/*
+ * The max frequency mperf is ticking at (in C0), either retrieved via:
+ *   1) calculated after measurements if we know TSC ticks at mperf/P0 frequency
+ *   2) cpufreq /sys/devices/.../cpu0/cpufreq/cpuinfo_max_freq at init time
+ * 1. Is preferred as it also works without cpufreq subsystem (e.g. on Xen)
+ */
+static unsigned long max_frequency;
+
 static unsigned long long tsc_at_measure_start;
 static unsigned long long tsc_at_measure_end;
-static unsigned long max_frequency;
 static unsigned long long *mperf_previous_count;
 static unsigned long long *aperf_previous_count;
 static unsigned long long *mperf_current_count;
 static unsigned long long *aperf_current_count;
+
 /* valid flag for all CPUs. If a MSR read failed it will be zero */
 static int *is_valid;
 
 static int mperf_get_tsc(unsigned long long *tsc)
 {
-       return read_msr(0, MSR_TSC, tsc);
+       int ret;
+       ret = read_msr(0, MSR_TSC, tsc);
+       if (ret)
+               dprint("Reading TSC MSR failed, returning %llu\n", *tsc);
+       return ret;
 }
 
 static int mperf_init_stats(unsigned int cpu)
@@ -97,36 +114,11 @@ static int mperf_measure_stats(unsigned int cpu)
        return 0;
 }
 
-/*
- * get_average_perf()
- *
- * Returns the average performance (also considers boosted frequencies)
- *
- * Input:
- *   aperf_diff: Difference of the aperf register over a time period
- *   mperf_diff: Difference of the mperf register over the same time period
- *   max_freq:   Maximum frequency (P0)
- *
- * Returns:
- *   Average performance over the time period
- */
-static unsigned long get_average_perf(unsigned long long aperf_diff,
-                                     unsigned long long mperf_diff)
-{
-       unsigned int perf_percent = 0;
-       if (((unsigned long)(-1) / 100) < aperf_diff) {
-               int shift_count = 7;
-               aperf_diff >>= shift_count;
-               mperf_diff >>= shift_count;
-       }
-       perf_percent = (aperf_diff * 100) / mperf_diff;
-       return (max_frequency * perf_percent) / 100;
-}
-
 static int mperf_get_count_percent(unsigned int id, double *percent,
                                   unsigned int cpu)
 {
        unsigned long long aperf_diff, mperf_diff, tsc_diff;
+       unsigned long long timediff;
 
        if (!is_valid[cpu])
                return -1;
@@ -136,11 +128,19 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
 
        mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu];
        aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
-       tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
 
-       *percent = 100.0 * mperf_diff / tsc_diff;
-       dprint("%s: mperf_diff: %llu, tsc_diff: %llu\n",
-              mperf_cstates[id].name, mperf_diff, tsc_diff);
+       if (max_freq_mode == MAX_FREQ_TSC_REF) {
+               tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
+               *percent = 100.0 * mperf_diff / tsc_diff;
+               dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
+                      mperf_cstates[id].name, mperf_diff, tsc_diff);
+       } else if (max_freq_mode == MAX_FREQ_SYSFS) {
+               timediff = timespec_diff_us(time_start, time_end);
+               *percent = 100.0 * mperf_diff / timediff;
+               dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n",
+                      mperf_cstates[id].name, mperf_diff, timediff);
+       } else
+               return -1;
 
        if (id == Cx)
                *percent = 100.0 - *percent;
@@ -154,7 +154,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
 static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
                                unsigned int cpu)
 {
-       unsigned long long aperf_diff, mperf_diff;
+       unsigned long long aperf_diff, mperf_diff, time_diff, tsc_diff;
 
        if (id != AVG_FREQ)
                return 1;
@@ -165,11 +165,21 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
        mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu];
        aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
 
-       /* Return MHz for now, might want to return KHz if column width is more
-          generic */
-       *count = get_average_perf(aperf_diff, mperf_diff) / 1000;
-       dprint("%s: %llu\n", mperf_cstates[id].name, *count);
+       if (max_freq_mode == MAX_FREQ_TSC_REF) {
+               /* Calculate max_freq from TSC count */
+               tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
+               time_diff = timespec_diff_us(time_start, time_end);
+               max_frequency = tsc_diff / time_diff;
+       }
 
+       *count = max_frequency * ((double)aperf_diff / mperf_diff);
+       dprint("%s: Average freq based on %s maximum frequency:\n",
+              mperf_cstates[id].name,
+              (max_freq_mode == MAX_FREQ_TSC_REF) ? "TSC calculated" : "sysfs read");
+       dprint("%max_frequency: %lu", max_frequency);
+       dprint("aperf_diff: %llu\n", aperf_diff);
+       dprint("mperf_diff: %llu\n", mperf_diff);
+       dprint("avg freq:   %llu\n", *count);
        return 0;
 }
 
@@ -178,6 +188,7 @@ static int mperf_start(void)
        int cpu;
        unsigned long long dbg;
 
+       clock_gettime(CLOCK_REALTIME, &time_start);
        mperf_get_tsc(&tsc_at_measure_start);
 
        for (cpu = 0; cpu < cpu_count; cpu++)
@@ -193,32 +204,104 @@ static int mperf_stop(void)
        unsigned long long dbg;
        int cpu;
 
-       mperf_get_tsc(&tsc_at_measure_end);
-
        for (cpu = 0; cpu < cpu_count; cpu++)
                mperf_measure_stats(cpu);
 
+       mperf_get_tsc(&tsc_at_measure_end);
+       clock_gettime(CLOCK_REALTIME, &time_end);
+
        mperf_get_tsc(&dbg);
        dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
 
        return 0;
 }
 
-struct cpuidle_monitor mperf_monitor;
-
-struct cpuidle_monitor *mperf_register(void)
+/*
+ * Mperf register is defined to tick at P0 (maximum) frequency
+ *
+ * Instead of reading out P0 which can be tricky to read out from HW,
+ * we use TSC counter if it reliably ticks at P0/mperf frequency.
+ *
+ * Still try to fall back to:
+ * /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
+ * on older Intel HW without invariant TSC feature.
+ * Or on AMD machines where TSC does not tick at P0 (do not exist yet, but
+ * it's still double checked (MSR_AMD_HWCR)).
+ *
+ * On these machines the user would still get useful mperf
+ * stats when acpi-cpufreq driver is loaded.
+ */
+static int init_maxfreq_mode(void)
 {
+       int ret;
+       unsigned long long hwcr;
        unsigned long min;
 
-       if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
-               return NULL;
-
-       /* Assume min/max all the same on all cores */
+       if (!cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC)
+               goto use_sysfs;
+
+       if (cpupower_cpu_info.vendor == X86_VENDOR_AMD) {
+               /* MSR_AMD_HWCR tells us whether TSC runs at P0/mperf
+                * freq.
+                * A test whether hwcr is accessable/available would be:
+                * (cpupower_cpu_info.family > 0x10 ||
+                *   cpupower_cpu_info.family == 0x10 &&
+                *   cpupower_cpu_info.model >= 0x2))
+                * This should be the case for all aperf/mperf
+                * capable AMD machines and is therefore safe to test here.
+                * Compare with Linus kernel git commit: acf01734b1747b1ec4
+                */
+               ret = read_msr(0, MSR_AMD_HWCR, &hwcr);
+               /*
+                * If the MSR read failed, assume a Xen system that did
+                * not explicitly provide access to it and assume TSC works
+               */
+               if (ret != 0) {
+                       dprint("TSC read 0x%x failed - assume TSC working\n",
+                              MSR_AMD_HWCR);
+                       return 0;
+               } else if (1 & (hwcr >> 24)) {
+                       max_freq_mode = MAX_FREQ_TSC_REF;
+                       return 0;
+               } else { /* Use sysfs max frequency if available */ }
+       } else if (cpupower_cpu_info.vendor == X86_VENDOR_INTEL) {
+               /*
+                * On Intel we assume mperf (in C0) is ticking at same
+                * rate than TSC
+                */
+               max_freq_mode = MAX_FREQ_TSC_REF;
+               return 0;
+       }
+use_sysfs:
        if (cpufreq_get_hardware_limits(0, &min, &max_frequency)) {
                dprint("Cannot retrieve max freq from cpufreq kernel "
                       "subsystem\n");
-               return NULL;
+               return -1;
        }
+       max_freq_mode = MAX_FREQ_SYSFS;
+       return 0;
+}
+
+/*
+ * This monitor provides:
+ *
+ * 1) Average frequency a CPU resided in
+ *    This always works if the CPU has aperf/mperf capabilities
+ *
+ * 2) C0 and Cx (any sleep state) time a CPU resided in
+ *    Works if mperf timer stops ticking in sleep states which
+ *    seem to be the case on all current HW.
+ * Both is directly retrieved from HW registers and is independent
+ * from kernel statistics.
+ */
+struct cpuidle_monitor mperf_monitor;
+struct cpuidle_monitor *mperf_register(void)
+{
+       if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
+               return NULL;
+
+       if (init_maxfreq_mode())
+               return NULL;
 
        /* Free this at program termination */
        is_valid = calloc(cpu_count, sizeof(int));